home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / comm / mail / YAM23src.lha / Source / YAM_MA.c < prev    next >
C/C++ Source or Header  |  2001-06-06  |  105KB  |  2,407 lines

  1. /***************************************************************************
  2.  
  3.  YAM - Yet Another Mailer
  4.  Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
  5.  Copyright (C) 2000-2001 by YAM Open Source Team
  6.  
  7.  This program is free software; you can redistribute it and/or modify
  8.  it under the terms of the GNU General Public License as published by
  9.  the Free Software Foundation; either version 2 of the License, or
  10.  (at your option) any later version.
  11.  
  12.  This program is distributed in the hope that it will be useful,
  13.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  GNU General Public License for more details.
  16.  
  17.  You should have received a copy of the GNU General Public License
  18.  along with this program; if not, write to the Free Software
  19.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20.  
  21.  YAM Official Support Site :  http://www.yam.ch
  22.  YAM OpenSource project    :  http://sourceforge.net/projects/yamos/
  23.  
  24.  $Id: YAM_MA.c,v 1.21.2.1 2001/06/06 20:35:19 laursen Exp $
  25.  
  26. ***************************************************************************/
  27.  
  28. #include "YAM.h"
  29. #include "YAM_rexx.h"
  30.  
  31. /* local protos */
  32. LOCAL ULONG MA_GetSortType(int);
  33. LOCAL struct Mail **MA_CreateFullList(struct Folder*);
  34. LOCAL struct Mail *MA_MoveCopySingle(struct Mail*, int, struct Folder*, struct Folder*, BOOL);
  35. LOCAL void MA_UpdateStatus(void);
  36. LOCAL char *AppendRcpt(char*, struct Person*, BOOL);
  37. LOCAL int MA_CmpDate(struct Mail**, struct Mail**);
  38. LOCAL void MA_InsertIntroText(FILE*, char*, struct ExpandTextData*);
  39. LOCAL void MA_EditorNotification(int);
  40. LOCAL void MA_SetupQuoteString(struct WR_ClassData*, struct ExpandTextData*, struct Mail*);
  41. LOCAL int MA_CheckWriteWindow(int);
  42. LOCAL struct Person *MA_GetAddressSelect(struct Mail*);
  43. LOCAL char *MA_GetRealSubject(char*);
  44. LOCAL int MA_MailCompare(struct Mail*, struct Mail*, int);
  45.  
  46. /***************************************************************************
  47.  Module: Main
  48. ***************************************************************************/
  49.  
  50. /*** Private functions ***/
  51. /// MA_GetSortType
  52. //  Calculates value for sort indicator
  53. LOCAL ULONG MA_GetSortType(int sort)
  54. {
  55.    ULONG sort2col[8] = { 0,4,6,1,1,3,5,0 };
  56.    if (sort > 0) return sort2col[abs(sort)];
  57.    else return sort2col[abs(sort)] | MUIV_NList_SortTypeAdd_2Values;
  58. }
  59.  
  60. ///
  61. /// MA_SetSortFlag
  62. //  Sets sort indicators in message listview header
  63. void MA_SetSortFlag(void)
  64. {
  65.    struct Folder *fo = FO_GetCurrentFolder();
  66.    set(G->MA->GUI.NL_MAILS, MUIA_NList_SortType, MA_GetSortType(fo->Sort[0]));
  67.    set(G->MA->GUI.NL_MAILS, MUIA_NList_SortType2, MA_GetSortType(fo->Sort[1]));
  68. }
  69.  
  70. ///
  71. /// MA_ChangeTransfer
  72. //  Disables menus and toolbar buttons during transfer operations
  73. void MA_ChangeTransfer(BOOL on)
  74. {
  75.    struct MA_GUIData *gui = &G->MA->GUI;
  76.    if (gui->TO_TOOLBAR) DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_MultiSet, MUIV_Toolbar_Set_Ghosted, !on, 10,11, -1);
  77.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, on, gui->MI_IMPORT, gui->MI_EXPORT, gui->MI_SENDALL, gui->MI_EXCHANGE, gui->MI_GETMAIL, gui->MI_CSINGLE, NULL);
  78. }
  79.  
  80. ///
  81. /// MA_ChangeSelectedFunc
  82. //  User selected some message(s) in the message list
  83. void SAVEDS MA_ChangeSelectedFunc(void)
  84. {
  85.    struct MA_GUIData *gui = &G->MA->GUI;
  86.    struct Folder *fo = FO_GetCurrentFolder();
  87.    int selected, type, i;
  88.    BOOL active, hasattach = FALSE, beingedited = FALSE;
  89.    struct Mail *mail;
  90.  
  91.    if (!fo) return;
  92.    type = fo->Type;
  93.    DoMethod(gui->NL_MAILS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &mail);
  94.    if ((active = (mail != NULL))) if (mail->Flags & MFLAG_MULTIPART) hasattach = TRUE;
  95.    for (i = 0; i < MAXWR; i++) if (mail && G->WR[i]) if (G->WR[i]->Mail == mail) beingedited = TRUE;
  96.    if (!mail) if (!GetMUI(gui->NL_MAILS, MUIA_NList_Entries)) set(gui->WI, MUIA_Window_ActiveObject, gui->LV_FOLDERS);
  97.    DoMethod(gui->NL_MAILS, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Ask, &selected);
  98.    if (gui->TO_TOOLBAR)
  99.    {
  100.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_Set, 1, MUIV_Toolbar_Set_Ghosted, !active || !OUTGOING(type) || beingedited);
  101.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_Set, 0, MUIV_Toolbar_Set_Ghosted, !active);
  102.       DoMethod(gui->TO_TOOLBAR, MUIM_Toolbar_MultiSet, MUIV_Toolbar_Set_Ghosted, !active && !selected, 2,3,4,7,8, -1);
  103.    }
  104.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active || selected,
  105.       gui->MI_MOVE, gui->MI_DELETE, gui->MI_GETADDRESS, gui->MI_REPLY, gui->MI_FORWARD, gui->MI_STATUS,
  106.       gui->MI_EXPMSG, gui->MI_COPY, gui->MI_PRINT, gui->MI_SAVE, gui->MI_CHSUBJ, NULL);
  107.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active, gui->MI_READ, gui->MI_BOUNCE, NULL);
  108.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, active && OUTGOING(type) && !beingedited, gui->MI_EDIT, NULL);
  109.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, type == FT_OUTGOING && (active || selected), gui->MI_SEND, gui->MI_TOHOLD, gui->MI_TOQUEUED, NULL);
  110.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, !OUTGOING(type) && (active || selected) , gui->MI_TOREAD, gui->MI_TOUNREAD, NULL);
  111.    DoMethod(G->App, MUIM_MultiSet, MUIA_Menuitem_Enabled, hasattach && (active || selected), gui->MI_ATTACH, gui->MI_SAVEATT, gui->MI_REMATT, NULL);
  112. }
  113. MakeHook(MA_ChangeSelectedHook, MA_ChangeSelectedFunc);
  114.  
  115. ///
  116. /// MA_SetMessageInfoFunc
  117. //  Builds help bubble for message list
  118. void SAVEDS MA_SetMessageInfoFunc(void)
  119. {
  120.    static char buffer[SIZE_DEFAULT+SIZE_SUBJECT+2*SIZE_REALNAME+2*SIZE_ADDRESS+SIZE_MFILE];
  121.    char *sh = NULL;
  122.    struct Mail *mail = MA_GetActiveMail(NULL, NULL, NULL);   
  123.    if (mail) SPrintF(sh = buffer, GetStr(MSG_MA_MessageInfo), mail->From.RealName, mail->From.Address, mail->To.RealName, mail->To.Address, mail->Subject, DateStamp2String(&mail->Date, C->SwatchBeat ? DSS_DATEBEAT : DSS_DATETIME), mail->MailFile, mail->Size);
  124.    set(G->MA->GUI.NL_MAILS, MUIA_ShortHelp, sh);
  125. }
  126. MakeHook(MA_SetMessageInfoHook, MA_SetMessageInfoFunc);
  127.  
  128. ///
  129. /// MA_SetFolderInfoFunc
  130. //  Builds help bubble for folder list
  131. void SAVEDS MA_SetFolderInfoFunc(void)
  132. {
  133.    static char buffer[SIZE_DEFAULT+SIZE_NAME+SIZE_PATH];
  134.    char *sh = NULL;
  135.    struct Folder *fo = FO_GetCurrentFolder();      
  136.    if (fo->Type != FT_SEPARATOR) SPrintF(sh = buffer, GetStr(MSG_MA_FolderInfo), fo->Name, fo->Path, fo->Size, fo->Total, fo->New, fo->Unread);
  137.    set(G->MA->GUI.NL_FOLDERS, MUIA_ShortHelp, sh);
  138. }
  139. MakeHook(MA_SetFolderInfoHook, MA_SetFolderInfoFunc);
  140.  
  141. ///
  142. /// MA_GetActiveMail
  143. //  Returns pointers to the active message and folder
  144. struct Mail *MA_GetActiveMail(struct Folder *forcefolder, struct Folder **folderp, int *activep)
  145. {
  146.    struct Folder *folder;
  147.    int active;
  148.    struct Mail *mail = NULL;
  149.  
  150.    folder = forcefolder ? forcefolder : FO_GetCurrentFolder();
  151.    MA_GetIndex(folder);
  152.    get(G->MA->GUI.NL_MAILS, MUIA_NList_Active, &active);
  153.    if (active != MUIV_NList_Active_Off) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_GetEntry, active, &mail);
  154.    if (folderp) *folderp = folder;
  155.    if (activep) *activep = active;
  156.    return mail;
  157. }
  158.  
  159. ///
  160. /// MA_SetMailStatus
  161. //  Sets the status of a message
  162. void MA_SetMailStatus(struct Mail *mail, int stat)
  163. {
  164.    struct MailInfo *mi;
  165.    char statstr[3];
  166.    int pf;
  167.  
  168.    strcpy(statstr, Status[stat&0xFF]);
  169.    if ((pf = ((mail->Flags & 0x0700) >> 8))) sprintf(statstr+1, "%c", pf+'0');
  170.    if (stat != mail->Status)
  171.    {
  172.       mail->Status = stat&0xFF;
  173.       MA_ExpireIndex(mail->Folder);
  174.       mi = GetMailInfo(mail);
  175.       SetComment(mi->FName, statstr);
  176.       if (mi->Display) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Redraw, mi->Pos);
  177.    }
  178.    else SetComment(GetMailFile(NULL, NULL, mail), statstr);
  179. }
  180.  
  181. ///
  182. /// MA_CreateFullList
  183. //  Builds a list containing all messages in a folder
  184. LOCAL struct Mail **MA_CreateFullList(struct Folder *fo)
  185. {
  186.    int selected = fo->Total;
  187.    struct Mail *mail, **mlist = NULL;
  188.  
  189.    if (selected) if ((mlist = calloc(selected+2, sizeof(struct Mail *))))
  190.    {
  191.       mlist[0] = (struct Mail *)selected;
  192.       mlist[1] = (struct Mail *)2;
  193.       for (selected = 2, mail = fo->Messages; mail; selected++, mail = mail->Next)
  194.          mlist[selected] = mail;
  195.    }
  196.    return mlist;
  197. }
  198.  
  199. ///
  200. /// MA_CreateMarkedList
  201. //  Builds a linked list containing the selected messages
  202. struct Mail **MA_CreateMarkedList(APTR lv)
  203. {
  204.    int id, selected;
  205.    struct Mail *mail, **mlist = NULL;
  206.  
  207.    DoMethod(lv, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_Ask, &selected);
  208.    if (selected)
  209.    {
  210.       if ((mlist = calloc(selected+2, sizeof(struct Mail *))))
  211.       {
  212.          mlist[0] = (struct Mail *)selected;
  213.          mlist[1] = (struct Mail *)1;
  214.          for (selected = 2, id = MUIV_NList_NextSelected_Start; ; selected++)
  215.          {
  216.             DoMethod(lv, MUIM_NList_NextSelected, &id);
  217.             if (id == MUIV_NList_NextSelected_End) break;
  218.             DoMethod(lv, MUIM_NList_GetEntry, id, &mail);
  219.             mail->Position = id;
  220.             mlist[selected] = mail;
  221.          }
  222.       }
  223.    }
  224.    else
  225.    {
  226.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &mail);
  227.       if (mail) if ((mlist = calloc(3, sizeof(struct Mail *))))
  228.       {
  229.          get(G->MA->GUI.NL_MAILS, MUIA_NList_Active, &id);
  230.          mail->Position = id;
  231.          mlist[0] = (struct Mail *)1;
  232.          mlist[2] = mail;
  233.       }
  234.    }
  235.    return mlist;
  236. }
  237.  
  238. ///
  239. /// MA_DeleteSingle
  240. //  Deletes a single message
  241. void MA_DeleteSingle(struct Mail *mail, BOOL forceatonce)
  242. {
  243.    if (C->RemoveAtOnce || mail->Folder->Type == FT_DELETED || forceatonce)
  244.    {        
  245.       struct MailInfo *mi = GetMailInfo(mail);
  246.       AppendLogVerbose(21, GetStr(MSG_LOG_DeletingVerbose), AddrName(mail->From), mail->Subject, mail->Folder->Name, "");
  247.       DeleteFile(mi->FName);
  248.       if (mi->Display) DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Remove, mi->Pos);
  249.       RemoveMailFromList(mail);
  250.    }
  251.    else MA_MoveCopy(mail, mail->Folder, FO_GetFolderByType(FT_DELETED, NULL), FALSE);
  252. }
  253.  
  254. ///
  255. /// MA_MoveCopySingle
  256. //  Moves or copies a single message from one folder to another
  257. LOCAL struct Mail *MA_MoveCopySingle(struct Mail *mail, int pos, struct Folder *from, struct Folder *to, BOOL copyit)
  258. {
  259.    struct Mail cmail = *mail;
  260.    char mfile[SIZE_MFILE];
  261.    APTR lv;
  262.  
  263.    strcpy(mfile, mail->MailFile);
  264.    if (TransferMailFile(copyit, mail, to))
  265.    {
  266.       strcpy(cmail.MailFile, mail->MailFile);
  267.       if (copyit) AppendLogVerbose(25, GetStr(MSG_LOG_CopyingVerbose), AddrName(mail->From), mail->Subject, from->Name, to->Name);
  268.              else AppendLogVerbose(23, GetStr(MSG_LOG_MovingVerbose),  AddrName(mail->From), mail->Subject, from->Name, to->Name);
  269.       if (copyit) strcpy(mail->MailFile, mfile);
  270.       else
  271.       {
  272.          if ((lv = WhichLV(from))) DoMethod(lv, MUIM_NList_Remove, pos);
  273.          RemoveMailFromList(mail);
  274.       }
  275.       mail = AddMailToList(&cmail, to);
  276.       if ((lv = WhichLV(to))) DoMethod(lv, MUIM_NList_InsertSingle, mail, MUIV_NList_Insert_Sorted);
  277.       if (mail->Status == STATUS_SNT && to->Type == FT_OUTGOING) MA_SetMailStatus(mail, STATUS_WFS);
  278.       return mail;
  279.    }
  280.    return NULL;
  281. }
  282.  
  283. ///
  284. /// MA_MoveCopy
  285. //  Moves or copies messages from one folder to another
  286. void MA_MoveCopy(struct Mail *mail, struct Folder *frombox, struct Folder *tobox, BOOL copyit)
  287. {
  288.    APTR lv;
  289.    struct MailInfo *mi;
  290.    struct Mail **mlist;
  291.    int i, pos, selected = 0;
  292.   
  293.    if (frombox == tobox && !copyit) return;
  294.    if (!(lv = WhichLV(frombox)) && !mail) return;
  295.    if (mail)
  296.    {
  297.       selected = 1;
  298.       mi = GetMailInfo(mail);
  299.       MA_MoveCopySingle(mail, mi->Pos, frombox, tobox, copyit);
  300.    }
  301.    else if ((mlist = MA_CreateMarkedList(lv)))
  302.    {
  303.       selected = (int)*mlist;
  304.       set(lv, MUIA_NList_Quiet, TRUE);
  305.       Busy(GetStr(MSG_BusyMoving), itoa(selected), 0, selected);
  306.       for (i = 0; i < selected; i++)
  307.       {
  308.          Busy(NULL, NULL, i, 0);
  309.          mail = mlist[i+2];
  310.          if (copyit) pos = mail->Position; else { mi = GetMailInfo(mail); pos = mi->Pos; }
  311.          MA_MoveCopySingle(mail, pos, frombox, tobox, copyit);
  312.       }
  313.       BusyEnd;
  314.       set(lv, MUIA_NList_Quiet, FALSE);
  315.       free(mlist);
  316.    }
  317.    if (copyit) AppendLogNormal(24, GetStr(MSG_LOG_Copying), (void *)selected, FolderName(frombox), FolderName(tobox), "");
  318.           else AppendLogNormal(22, GetStr(MSG_LOG_Moving),  (void *)selected, FolderName(frombox), FolderName(tobox), "");
  319.    if (!copyit) DisplayStatistics(frombox);
  320.    DisplayStatistics(tobox);
  321.    MA_ChangeSelectedFunc();
  322. }
  323.  
  324. ///
  325. /// MA_UpdateStatus
  326. //  Changes status of all new messages to unread
  327. LOCAL void MA_UpdateStatus(void)
  328. {
  329.    int i;
  330.    struct Mail *mail;
  331.    struct Folder **flist;
  332.  
  333.    if ((flist = FO_CreateList()))
  334.    {
  335.       for (i = 1; i <= (int)*flist; i++) if (!OUTGOING(flist[i]->Type)) if (flist[i]->LoadedMode == 2)
  336.       {
  337.          BOOL updated = FALSE;
  338.          for (mail = flist[i]->Messages; mail; mail = mail->Next)
  339.             if (mail->Status == STATUS_NEW) { updated = TRUE; MA_SetMailStatus(mail, STATUS_UNR); }
  340.          if (updated) DisplayStatistics(flist[i]);
  341.       }
  342.       free(flist);
  343.    }
  344. }
  345. ///
  346.  
  347. /*** Main button functions ***/
  348. /// MA_ReadMessage
  349. //  Loads active message into a read window
  350. void SAVEDS ASM MA_ReadMessage(REG(a1,int *arg))
  351. {
  352.    static int lastwin = 0;
  353.    struct Mail *mail;
  354.    int i, winnum;
  355.  
  356.    if ((mail = MA_GetActiveMail(ANYBOX, NULL, NULL)))
  357.    {
  358.       for (i = 0; i < MAXRE; i++) if (G->RE[i]) if (mail == G->RE[i]->MailPtr)
  359.       {
  360.          DoMethod(G->RE[i]->GUI.WI, MUIM_Window_ToFront);
  361.          set(G->RE[i]->GUI.WI, MUIA_Window_Activate, TRUE);
  362.          return;
  363.       }
  364.       if ((winnum = RE_Open(C->MultipleWindows ? -1 : lastwin, TRUE)) != -1)
  365.       {
  366.          lastwin = winnum;
  367.          if (SafeOpenWindow(G->RE[winnum]->GUI.WI)) RE_ReadMessage(winnum, mail);
  368.          else DisposeModulePush(&G->RE[winnum]);
  369.       }
  370.    }
  371. }
  372. MakeHook(MA_ReadMessageHook, MA_ReadMessage);
  373.  
  374. ///
  375. /// AppendRcpt
  376. //  Appends a recipient address to a string
  377. LOCAL char *AppendRcpt(char *sbuf, struct Person *pe, BOOL excludeme)
  378. {
  379.    char *ins;
  380.    if (strchr(pe->Address,'@'))
  381.       ins = BuildAddrName2(pe);
  382.    else
  383.    {
  384.       char addr[SIZE_ADDRESS];
  385.       strcpy(addr, pe->Address);
  386.       strcat(addr, strchr(C->EmailAddress, '@'));
  387.       ins = BuildAddrName(addr, pe->RealName);
  388.    }
  389.    if (excludeme) if (!stricmp(pe->Address, C->EmailAddress)) return sbuf;
  390.    if (stristr(sbuf, ins)) return sbuf;
  391.    if (*sbuf) sbuf = StrBufCat(sbuf, ", ");
  392.    return StrBufCat(sbuf, ins);
  393. }
  394.  
  395. ///
  396. /// MA_CmpDate
  397. //  Compares two messages by date
  398. LOCAL int MA_CmpDate(struct Mail **pentry1, struct Mail **pentry2)
  399. {
  400.    return CompareDates(&(pentry2[0]->Date), &(pentry1[0]->Date));
  401. }
  402.  
  403. ///
  404. /// MA_InsertIntroText
  405. //  Inserts a phrase into the message text
  406. LOCAL void MA_InsertIntroText(FILE *fh, char *text, struct ExpandTextData *etd)
  407. {
  408.    if (*text)
  409.    {
  410.       char *sbuf;
  411.       sbuf = ExpandText(text, etd);
  412.       fprintf(fh, "%s\n", sbuf);
  413.       FreeStrBuf(sbuf);
  414.    }
  415. }
  416.  
  417. ///
  418. /// MA_EditorNotification
  419. //  Starts file notification for temporary message file
  420. LOCAL void MA_EditorNotification(int winnum)
  421. {
  422.    FileToEditor(G->WR_Filename[winnum], G->WR[winnum]->GUI.TE_EDIT);
  423.    StartNotify(&G->WR_NRequest[winnum]);
  424.    set(G->WR[winnum]->GUI.TE_EDIT, MUIA_TextEditor_HasChanged, FALSE);
  425. }
  426.  
  427. ///
  428. /// MA_SetupQuoteString
  429. //  Creates quote string by replacing variables with values
  430. LOCAL void MA_SetupQuoteString(struct WR_ClassData *wr, struct ExpandTextData *etd, struct Mail *mail)
  431. {
  432.    struct ExpandTextData l_etd;
  433.    char *sbuf;
  434.    if (!etd) etd = &l_etd;
  435.    etd->OS_Name      = mail ? (*(mail->From.RealName) ? mail->From.RealName : mail->From.Address) : "";
  436.    etd->OS_Address   = mail ? mail->From.Address : "";
  437.    etd->OM_Subject   = mail ? mail->Subject : "";
  438.    etd->OM_Date      = mail ? &(mail->Date) : &(G->StartDate);
  439.    etd->R_Name       = "";
  440.    etd->R_Address    = "";
  441.    sbuf = ExpandText(C->QuoteText, etd);
  442.    stccpy(wr->QuoteText, TrimEnd(sbuf), SIZE_DEFAULT);
  443.    FreeStrBuf(sbuf);
  444.     stccpy(wr->AltQuoteText, C->AltQuoteText, SIZE_SMALL);
  445. }
  446.  
  447. ///
  448. /// MA_CheckWriteWindow
  449. //  Opens a write window
  450. LOCAL int MA_CheckWriteWindow(int winnum)
  451. {
  452.    if (SafeOpenWindow(G->WR[winnum]->GUI.WI)) return winnum;
  453.    WR_Cleanup(winnum);
  454.    DisposeModulePush(&G->WR[winnum]);
  455.    return -1;
  456. }
  457.  
  458. ///
  459. /// MA_NewNew
  460. //  Creates a new, empty message
  461. int MA_NewNew(struct Mail *mail, int flags)
  462. {
  463.    BOOL quiet = flags & NEWF_QUIET;
  464.    struct Folder *folder = FO_GetCurrentFolder();
  465.    int winnum = -1;
  466.    struct WR_ClassData *wr;
  467.    FILE *out;
  468.  
  469.    /* First check if the basic configuration is okay, then open write window */
  470.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  471.    {
  472.       if ((out = fopen(G->WR_Filename[winnum], "w")))
  473.       {
  474.          wr = G->WR[winnum];
  475.          wr->Mode = NEW_NEW;
  476.          wr->Mail = mail;
  477.          if (mail) setstring(wr->GUI.ST_TO, BuildAddrName2(GetReturnAddress(mail)));
  478.          else if (folder && folder->Type != FT_INCOMING) {
  479.             if (folder->MLAddress[0]) setstring(wr->GUI.ST_TO, folder->MLAddress);
  480.             if (folder->MLFromAddress[0]) setstring(wr->GUI.ST_FROM, folder->MLFromAddress);
  481.             if (folder->MLReplyToAddress[0]) setstring(wr->GUI.ST_REPLYTO, folder->MLReplyToAddress);
  482.          }
  483.          MA_SetupQuoteString(wr, NULL, NULL);
  484.          MA_InsertIntroText(out, C->NewIntro, NULL);
  485.          MA_InsertIntroText(out, C->Greetings, NULL);
  486.          fclose(out);
  487.          WR_AddSignature(G->WR_Filename[winnum], -1);
  488.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  489.          MA_EditorNotification(winnum);
  490.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  491.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  492.       } else DisposeModulePush(&G->WR[winnum]);
  493.    }
  494.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  495.    return winnum;
  496. }
  497.  
  498. ///
  499. /// MA_NewEdit
  500. //  Edits a message
  501. int MA_NewEdit(struct Mail *mail, int flags, int ReadwinNum)
  502. {
  503.    BOOL quiet = flags & NEWF_QUIET;
  504.    int i, winnum = -1;
  505.    struct Folder *folder;
  506.    struct WR_ClassData *wr;
  507.    struct ExtendedMail *email;
  508.    FILE *out;
  509.    char *cmsg, *sbuf;
  510.  
  511.     // return if mail is already being written/edited
  512.    for (i = 0; i < MAXWR; i++) if (G->WR[i] && G->WR[i]->Mail == mail) { DoMethod(G->WR[i]->GUI.WI, MUIM_Window_ToFront); return -1; }
  513.     // check if necessary settings fror writing are OK and open new window
  514.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  515.    {
  516.       if ((out = fopen(G->WR_Filename[winnum], "w")))
  517.       {
  518.          wr = G->WR[winnum];
  519.          wr->Mode = NEW_EDIT;
  520.          wr->Mail = mail;
  521.          wr->ReadwinNum = ReadwinNum;
  522.          folder = mail->Folder;
  523.          email = MA_ExamineMail(folder, mail->MailFile, NULL, TRUE);
  524.          MA_SetupQuoteString(wr, NULL, mail);
  525.          RE_InitPrivateRC(mail, PM_ALL);
  526.          cmsg = RE_ReadInMessage(4, RIM_EDIT);
  527.          fputs(cmsg, out);
  528.          free(cmsg);
  529.          strcpy(wr->MsgID, email->IRTMsgID);
  530.          setstring(wr->GUI.ST_SUBJECT, mail->Subject);
  531.          setstring(wr->GUI.ST_FROM, BuildAddrName2(&mail->From));
  532.          setstring(wr->GUI.ST_REPLYTO, BuildAddrName2(&mail->ReplyTo));
  533.          sbuf = StrBufCpy(NULL, BuildAddrName2(&mail->To));
  534.          if (mail->Flags & MFLAG_MULTIRCPT)
  535.          {
  536.             *sbuf = 0;
  537.             sbuf = AppendRcpt(sbuf, &mail->To, FALSE);
  538.             for (i = 0; i < email->NoSTo; i++) sbuf = AppendRcpt(sbuf, &email->STo[i], FALSE);
  539.             setstring(wr->GUI.ST_TO, sbuf);
  540.             *sbuf = 0;
  541.             for (i = 0; i < email->NoCC; i++) sbuf = AppendRcpt(sbuf, &email->CC[i], FALSE);
  542.             setstring(wr->GUI.ST_CC, sbuf);
  543.             *sbuf = 0;
  544.             for (i = 0; i < email->NoBCC; i++) sbuf = AppendRcpt(sbuf, &email->BCC[i], FALSE);
  545.             setstring(wr->GUI.ST_BCC, sbuf);
  546.          }
  547.          else setstring(wr->GUI.ST_TO, sbuf);
  548.          FreeStrBuf(sbuf);
  549.          if (email->Headers) setstring(wr->GUI.ST_EXTHEADER, email->Headers);
  550.          setcheckmark(wr->GUI.CH_DELSEND, email->DelSend);
  551.          setcheckmark(wr->GUI.CH_RECEIPT, email->RetRcpt);
  552.          setcheckmark(wr->GUI.CH_DISPNOTI, email->ReceiptType == RCPT_TYPE_ALL);
  553.          setcheckmark(wr->GUI.CH_ADDINFO, (mail->Flags&MFLAG_SENDERINFO) == MFLAG_SENDERINFO);
  554.          setcycle(wr->GUI.CY_IMPORTANCE, 1-mail->Importance);
  555.          setmutex(wr->GUI.RA_SIGNATURE, email->Signature);
  556.          setmutex(wr->GUI.RA_SECURITY, wr->OldSecurity = email->Security);
  557.          if (folder->Type != FT_OUTGOING) DoMethod(G->App, MUIM_MultiSet, MUIA_Disabled, TRUE, wr->GUI.BT_SEND, wr->GUI.BT_HOLD, NULL);
  558.          WR_SetupOldMail(winnum);
  559.          RE_FreePrivateRC();
  560.          fclose(out);
  561.          MA_FreeEMailStruct(email);
  562.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  563.          MA_EditorNotification(winnum);
  564.          sbuf = GetMUIStringPtr(wr->GUI.ST_TO);
  565.          set(wr->GUI.WI, MUIA_Window_ActiveObject, *sbuf ? wr->GUI.TE_EDIT : wr->GUI.ST_TO);
  566.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  567.       } else DisposeModulePush(&G->WR[winnum]);
  568.    }
  569.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  570.    return winnum;
  571. }
  572.  
  573. ///
  574. /// MA_NewBounce
  575. //  Bounces a message
  576. int MA_NewBounce(struct Mail *mail, int flags)
  577. {
  578.    BOOL quiet = flags & NEWF_QUIET;
  579.    int winnum = -1;
  580.    struct WR_ClassData *wr;
  581.  
  582.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, TRUE)) >= 0)
  583.    {
  584.       wr = G->WR[winnum];
  585.       wr->Mode = NEW_BOUNCE;
  586.       wr->Mail = mail;
  587.       if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  588.       set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  589.    }
  590.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  591.    return winnum;
  592. }
  593.  
  594. ///
  595. /// MA_NewForward
  596. //  Forwards a list of messages
  597. int MA_NewForward(struct Mail **mlist, int flags)
  598. {
  599.    BOOL quiet = flags & NEWF_QUIET;
  600.    char buffer[SIZE_LARGE];
  601.    int i, winnum = -1, mlen = (2+(int)mlist[0])*sizeof(struct Mail *);
  602.    struct WR_ClassData *wr;
  603.    struct Mail *mail;
  604.    struct ExtendedMail *email;
  605.    struct ExpandTextData etd;
  606.    FILE *out;
  607.    char *cmsg, *rsub;
  608.  
  609.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  610.    {
  611.       if ((out = fopen(G->WR_Filename[winnum], "w")))
  612.       {
  613.          wr = G->WR[winnum];
  614.          wr->Mode = NEW_FORWARD;
  615.          wr->MList = memcpy(malloc(mlen), mlist, mlen);
  616.          rsub = AllocStrBuf(SIZE_SUBJECT);
  617.          qsort(&mlist[2], (int)mlist[0], sizeof(struct Mail *), (int (*)(const void *, const void *))MA_CmpDate);
  618.          MA_InsertIntroText(out, C->NewIntro, NULL);
  619.          for (i = 0; i < (int)mlist[0]; i++)
  620.          {
  621.             mail = mlist[i+2];
  622.             email = MA_ExamineMail(mail->Folder, mail->MailFile, NULL, TRUE);
  623.             MA_SetupQuoteString(wr, &etd, mail);
  624.             etd.OM_MessageID = email->MsgID;
  625.             etd.R_Name = *mail->To.RealName ? mail->To.RealName : mail->To.Address;
  626.             etd.R_Address = mail->To.Address;
  627.             if (*mail->Subject)
  628.             {
  629.                sprintf(buffer, "%s (fwd)", mail->Subject);
  630.                if (!strstr(rsub, buffer))
  631.                {
  632.                   if (*rsub) rsub = StrBufCat(rsub, "; ");
  633.                   rsub = StrBufCat(rsub, buffer);
  634.                }
  635.             }
  636.             RE_InitPrivateRC(mail, PM_ALL);
  637.             etd.HeaderFile = G->RE[4]->FirstPart->Filename;
  638.             MA_InsertIntroText(out, C->ForwardIntro, &etd);
  639.             MA_FreeEMailStruct(email);
  640.             cmsg = RE_ReadInMessage(4, RIM_EDIT);
  641.             fputs(cmsg, out);
  642.             free(cmsg);
  643.             MA_InsertIntroText(out, C->ForwardFinish, &etd);
  644.             if (!(flags & NEWF_FWD_NOATTACH)) WR_SetupOldMail(winnum);
  645.             RE_FreePrivateRC();
  646.          }
  647.          MA_InsertIntroText(out, C->Greetings, NULL);
  648.          fclose(out);
  649.          WR_AddSignature(G->WR_Filename[winnum], -1);
  650.          setstring(wr->GUI.ST_SUBJECT, rsub);
  651.          FreeStrBuf(rsub);
  652.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  653.          MA_EditorNotification(winnum);
  654.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.ST_TO);
  655.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  656.       } else DisposeModulePush(&G->WR[winnum]);
  657.    }
  658.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  659.    return winnum;
  660. }
  661.  
  662. ///
  663. /// MA_NewReply
  664. //  Creates a reply to a list of messages
  665. int MA_NewReply(struct Mail **mlist, int flags)
  666. {
  667.    int j, i, repmode = 1, winnum = -1, mlen = (2+(int)mlist[0])*sizeof(struct Mail *);
  668.    BOOL doabort = FALSE, multi = (int)mlist[0] > 1, altpat = FALSE, quiet = flags & NEWF_QUIET;
  669.    struct WR_ClassData *wr;
  670.    struct Mail *mail;
  671.    struct ExtendedMail *email;
  672.    struct ExpandTextData etd;
  673.    struct Person *repto, rtml;
  674.    struct Folder **flist, *folder;
  675.    FILE *out;
  676.    char *mlistad = NULL, buffer[SIZE_LARGE];
  677.    char *cmsg, *rfrom = NULL, *rrepto = NULL, *rto = NULL, *rcc = NULL, *rsub = NULL;
  678.    char *domain;
  679.  
  680.    if (CO_IsValid()) if ((winnum = WR_Open(quiet ? 2 : -1, FALSE)) >= 0)
  681.    {
  682.       if ((out = fopen(G->WR_Filename[winnum], "w")))
  683.       {
  684.          wr = G->WR[winnum];
  685.          wr->Mode = NEW_REPLY;
  686.          wr->MList = memcpy(malloc(mlen), mlist, mlen);
  687.          rto = AllocStrBuf(SIZE_ADDRESS);
  688.          rcc = AllocStrBuf(SIZE_ADDRESS);
  689.          rsub = AllocStrBuf(SIZE_SUBJECT);
  690.          qsort(&mlist[2], (int)mlist[0], sizeof(struct Mail *), (int (*)(const void *, const void *))MA_CmpDate);
  691.          for (j = 0; j < (int)mlist[0]; j++)
  692.          {
  693.             mail = mlist[j+2];
  694.             folder = mail->Folder;
  695.             email = MA_ExamineMail(folder, mail->MailFile, NULL, TRUE);
  696.             MA_SetupQuoteString(wr, &etd, mail);
  697.             etd.OM_MessageID = email->MsgID;
  698.             if (*mail->Subject)
  699.             {
  700.                if (j) strcpy(buffer, mail->Subject); else sprintf(buffer, "Re: %s", MA_GetRealSubject(mail->Subject));
  701.                if (!strstr(rsub, buffer))
  702.                {
  703.                   if (*rsub) rsub = StrBufCat(rsub, "; ");
  704.                   rsub = StrBufCat(rsub, buffer);
  705.                }
  706.             }
  707.             if (!multi) strcpy(wr->MsgID, email->MsgID);
  708.  
  709.             if (folder)
  710.             {
  711.                            char tofld[SIZE_LARGE], fromfld[SIZE_LARGE];
  712.  
  713.                    strcpy(tofld, BuildAddrName2(&mail->To));
  714.                    strcpy(fromfld, BuildAddrName2(&mail->From));
  715.  
  716.                if (folder->Type == FT_INCOMING)
  717.                {
  718.                   if ((flist = FO_CreateList()))
  719.                   {
  720.                      for (i = 1; i <= (int)*flist; i++) if (flist[i]->MLPattern[0]) if (MatchNoCase(tofld, flist[i]->MLPattern)) {
  721.                         mlistad = flist[i]->MLAddress[0] ? flist[i]->MLAddress : fromfld;
  722.                         if (flist[i]->MLFromAddress[0])    rfrom  = flist[i]->MLFromAddress;
  723.                         if (flist[i]->MLReplyToAddress[0]) rrepto = flist[i]->MLReplyToAddress;
  724.                         break;
  725.                      }
  726.                      free(flist);
  727.                   }
  728.                }
  729.                else if (folder->MLPattern[0]) if (MatchNoCase(tofld, folder->MLPattern)) {
  730.                   mlistad = folder->MLAddress[0] ? folder->MLAddress : fromfld;
  731.                   if (folder->MLFromAddress[0])    rfrom  = folder->MLFromAddress;
  732.                   if (folder->MLReplyToAddress[0]) rrepto = folder->MLReplyToAddress;
  733.                }
  734.             }
  735.             if (mlistad && !(flags & (NEWF_REP_PRIVATE|NEWF_REP_MLIST)))
  736.             {
  737.                ExtractAddress(mlistad, repto=&rtml);
  738.                if (!strstr(rto, mlistad))
  739.                {
  740.                   if (*rto) rto = StrBufCat(rto, ", ");
  741.                   rto = StrBufCat(rto, mlistad);
  742.                }
  743.             }
  744.  
  745.             if (mail->Flags & MFLAG_MULTIRCPT)
  746.             {
  747.                 if (!(repmode = MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_ReplyReqOpt), GetStr(MSG_MA_ReplyReq))))
  748.               {
  749.                   MA_FreeEMailStruct(email);
  750.                 fclose(out);
  751.                 doabort = TRUE;
  752.                 goto abort_repl;
  753.               }
  754.             }
  755.  
  756.             repto = GetReturnAddress(mail);
  757.  
  758.             if (repmode == 1)
  759.             {
  760.                if (flags & NEWF_REP_PRIVATE) repto = &mail->From;
  761.                else if ((flags & NEWF_REP_MLIST) || mlistad);
  762.                else if (C->CompareAddress && *mail->ReplyTo.Address) if (stricmp(mail->From.Address, mail->ReplyTo.Address))
  763.                {
  764.                   sprintf(buffer, GetStr(MSG_MA_CompareReq), mail->From.Address, mail->ReplyTo.Address);
  765.                   switch (MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_Compare3ReqOpt), buffer))
  766.                   {
  767.                      case 3: rcc = AppendRcpt(rcc, &mail->From, FALSE);
  768.                      case 2: repto = &mail->ReplyTo; break;
  769.                      case 1: repto = &mail->From; break;
  770.                      case 0: MA_FreeEMailStruct(email); doabort = TRUE; fclose(out); goto abort_repl;
  771.                   }
  772.                }
  773.                rto = AppendRcpt(rto, repto, FALSE);
  774.             }
  775.             else
  776.             {
  777.                if (repmode == 2) rto = AppendRcpt(rto, GetReturnAddress(mail), FALSE);
  778.                rto = AppendRcpt(rto, &mail->To, TRUE);
  779.                for (i = 0; i < email->NoSTo; i++) rto = AppendRcpt(rto, &email->STo[i], TRUE);
  780.                for (i = 0; i < email->NoCC; i++) rcc = AppendRcpt(rcc, &email->CC[i], TRUE);
  781.             }
  782.  
  783.                         etd.R_Name = repto->RealName;
  784.             etd.R_Address = repto->Address;
  785.             altpat = FALSE;
  786.             if (!(domain = strchr(repto->Address,'@'))) domain = strchr(C->EmailAddress,'@');
  787.             if (*C->AltReplyPattern) if (MatchNoCase(domain, C->AltReplyPattern)) altpat = TRUE;
  788.             if (!j) MA_InsertIntroText(out, mlistad ? C->MLReplyHello : (altpat ? C->AltReplyHello : C->ReplyHello), &etd);
  789.             if (C->QuoteMessage && !(flags & NEWF_REP_NOQUOTE))
  790.             {
  791.                if (j) fputs("\n", out);
  792.                RE_InitPrivateRC(mail, PM_TEXTS);
  793.                etd.HeaderFile = G->RE[4]->FirstPart->Filename;
  794.                MA_InsertIntroText(out, mlistad ? C->MLReplyIntro : (altpat ? C->AltReplyIntro : C->ReplyIntro), &etd);
  795.                cmsg = RE_ReadInMessage(4, RIM_QUOTE);
  796.                QuoteWordWrap(cmsg, C->EdWrapMode ? C->EdWrapCol-strlen(wr->QuoteText)-1 : 1024, NULL, wr->QuoteText, out);
  797.                free(cmsg);
  798.                RE_FreePrivateRC();
  799.             }
  800.             MA_FreeEMailStruct(email);
  801.          }
  802.          MA_InsertIntroText(out, mlistad ? C->MLReplyBye : (altpat ? C->AltReplyBye: C->ReplyBye), &etd);
  803.          fclose(out);
  804.          WR_AddSignature(G->WR_Filename[winnum], mlistad ? folder->MLSignature: -1);
  805.  
  806.          /* If this is a reply to a mail belonging to a mailing list,
  807.             set the "From:" and "Reply-To:" addresses accordingly */
  808.          if (rfrom)  setstring(wr->GUI.ST_FROM,    rfrom);
  809.          if (rrepto) setstring(wr->GUI.ST_REPLYTO, rrepto);
  810.  
  811.          setstring(wr->GUI.ST_TO, rto);
  812.          setstring(*rto ? wr->GUI.ST_CC : wr->GUI.ST_TO, rcc);
  813.          setstring(wr->GUI.ST_SUBJECT, rsub);
  814.          if (!quiet) set(wr->GUI.WI, MUIA_Window_Open, TRUE);
  815.          MA_EditorNotification(winnum);
  816.          set(wr->GUI.WI, MUIA_Window_ActiveObject, wr->GUI.TE_EDIT);
  817.          if (C->LaunchAlways && !quiet) DoMethod(G->App, MUIM_CallHook, &WR_EditHook, winnum);
  818.       } else doabort = TRUE;
  819.   }
  820.    if (winnum >= 0 && !quiet) return MA_CheckWriteWindow(winnum);
  821.  
  822. abort_repl:
  823.  
  824.    if (doabort) DisposeModulePush(&G->WR[winnum]);
  825.    FreeStrBuf(rto);
  826.    FreeStrBuf(rcc);
  827.    FreeStrBuf(rsub);
  828.    return winnum;
  829. }
  830.  
  831. ///
  832. /// MA_RemoveAttach
  833. //  Removes attachments from a message
  834. void MA_RemoveAttach(struct Mail *mail)
  835. {
  836.    struct Part *part;
  837.    int f;
  838.    FILE *out, *in;
  839.    char *cmsg, buf[SIZE_LINE], fname[SIZE_PATHFILE], tfname[SIZE_PATHFILE];
  840.    struct Folder *fo = mail->Folder;
  841.  
  842.    sprintf(tfname, "%s.tmp", GetMailFile(fname, NULL, mail));
  843.    RE_InitPrivateRC(mail, PM_ALL);
  844.    cmsg = RE_ReadInMessage(4, RIM_QUIET);
  845.    if ((part = G->RE[4]->FirstPart->Next)) if (part->Next)
  846.       if ((out = fopen(tfname, "w")))
  847.       {
  848.          if ((in = fopen(G->RE[4]->FirstPart->Filename, "r")))
  849.          {
  850.             BOOL infield = FALSE, inbody = FALSE;
  851.             while (fgets(buf, SIZE_LINE, in))
  852.             {
  853.                if (!ISpace(*buf)) infield = !strnicmp(buf, "content-transfer-encoding", 25) || !strnicmp(buf, "content-type", 12);
  854.                if (!infield || inbody) fputs(buf, out);
  855.             }
  856.             fclose(in);
  857.          }
  858.          fputs("Content-Transfer-Encoding: 8bit\nContent-Type: text/plain; charset=iso-8859-1\n\n", out);
  859.          fputs(cmsg, out);
  860.          MA_ExpireIndex(mail->Folder);
  861.          fputs(GetStr(MSG_MA_AttachRemoved), out);
  862.          for (part = part->Next; part; part = part->Next)
  863.             fprintf(out, "%s (%ld %s, %s)\n", part->Name ? part->Name : GetStr(MSG_Unnamed), part->Size, GetStr(MSG_Bytes), part->ContentType);
  864.          fclose(out);
  865.          f = FileSize(tfname); fo->Size += f - mail->Size; mail->Size = f;
  866.          mail->Flags &= ~MFLAG_MULTIPART;
  867.          DeleteFile(fname);
  868.          if (fo->XPKType > 1) DoPack(tfname, fname, mail->Folder);
  869.          else RenameFile(tfname, fname);
  870.          MA_SetMailStatus(mail, mail->Status);
  871.          AppendLog(81, GetStr(MSG_LOG_CroppingAtt), mail->MailFile, mail->Folder->Name, "", "");
  872.       }
  873.    free(cmsg);
  874.    RE_FreePrivateRC();
  875. }
  876.  
  877. ///
  878. /// MA_RemoveAttachFunc
  879. //  Removes attachments from selected messages
  880. void SAVEDS MA_RemoveAttachFunc(void)
  881. {
  882.    struct Mail **mlist;
  883.    int i;
  884.  
  885.    if ((mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS)))
  886.    {
  887.       int selected = (int)*mlist;
  888.       Busy(GetStr(MSG_BusyRemovingAtt), "", 0, selected);
  889.       for (i = 0; i < selected; i++)
  890.       {
  891.          Busy(NULL, NULL, i, 0);
  892.          MA_RemoveAttach(mlist[i+2]);
  893.       }
  894.       DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  895.       MA_ChangeSelectedFunc();
  896.       DisplayStatistics(NULL);
  897.       BusyEnd;
  898.    }
  899. }
  900. MakeHook(MA_RemoveAttachHook, MA_RemoveAttachFunc);
  901.  
  902. ///
  903. /// MA_SaveAttachFunc
  904. //  Saves all attachments of selected messages to disk
  905. void SAVEDS MA_SaveAttachFunc(void)
  906. {
  907.    struct Mail **mlist, *mail;
  908.    struct Part *part;
  909.    char *cmsg;
  910.    int i;
  911.  
  912.    if ((mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS)))
  913.    {
  914.       if (ReqFile(ASL_DETACH, G->MA->GUI.WI, GetStr(MSG_RE_SaveMessage), 5, C->DetachDir, ""))
  915.          for (i = 0; i < (int)*mlist; i++)
  916.          {
  917.             RE_InitPrivateRC(mail = mlist[i+2], PM_ALL);
  918.             if ((cmsg = RE_ReadInMessage(4, RIM_QUIET)))
  919.             {
  920.                free(cmsg);
  921.                if ((part = G->RE[4]->FirstPart->Next)) if (part->Next)
  922.                   RE_SaveAll(4, G->ASLReq[ASL_DETACH]->fr_Drawer);
  923.             }
  924.             RE_FreePrivateRC();
  925.          }
  926.       free(mlist);
  927.    }
  928. }
  929. MakeHook(MA_SaveAttachHook, MA_SaveAttachFunc);
  930.  
  931. ///
  932. /// MA_SavePrintFunc
  933. //  Prints selected messages
  934. void SAVEDS ASM MA_SavePrintFunc(REG(a1,int *arg))
  935. {
  936.    BOOL doprint = *arg != 0;
  937.    struct TempFile *tf;
  938.    struct Mail **mlist;
  939.    char *cmsg;
  940.    int i;
  941.  
  942.    if (doprint && C->PrinterCheck) if (!CheckPrinter()) return;
  943.    if ((mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS)))
  944.    {
  945.       for (i = 0; i < (int)*mlist; i++)
  946.       {
  947.          RE_InitPrivateRC(mlist[i+2], PM_TEXTS);
  948.          if ((cmsg = RE_ReadInMessage(4, RIM_READ)))
  949.          {
  950.             if ((tf = OpenTempFile("w")))
  951.             {
  952.                fputs(cmsg, tf->FP);
  953.                fclose(tf->FP); tf->FP = NULL;
  954.                if (doprint) CopyFile("PRT:", 0, tf->Filename, 0);
  955.                else RE_Export(4, tf->Filename, "", "", 0, FALSE, FALSE, ContType[CT_TX_PLAIN]);
  956.                CloseTempFile(tf);
  957.             }
  958.             free(cmsg);
  959.          }
  960.          RE_FreePrivateRC();
  961.       }
  962.       free(mlist);
  963.    }
  964. }
  965. MakeHook(MA_SavePrintHook, MA_SavePrintFunc);
  966.  
  967. ///
  968. /// MA_NewMessage
  969. //  Starts a new message
  970. int MA_NewMessage(int mode, int flags)
  971. {
  972.    struct Mail *mail, **mlist = NULL;
  973.    int winnr = -1;
  974.    switch (mode)
  975.    {
  976.       case NEW_NEW:     winnr = MA_NewNew(NULL, flags);
  977.                         break;
  978.       case NEW_EDIT:    if ((mail = MA_GetActiveMail(ANYBOX, NULL, NULL))) winnr = MA_NewEdit(mail, flags, -1);
  979.                         break;
  980.       case NEW_BOUNCE:  if ((mail = MA_GetActiveMail(ANYBOX, NULL, NULL))) winnr = MA_NewBounce(mail, flags);
  981.                         break;
  982.       case NEW_FORWARD: if ((mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS))) winnr = MA_NewForward(mlist, flags);
  983.                         break;
  984.       case NEW_REPLY:   if ((mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS))) winnr = MA_NewReply(mlist, flags);
  985.                         break;
  986.    }
  987.    if (mlist) free(mlist);
  988.    return winnr;
  989. }
  990.  
  991. void SAVEDS ASM MA_NewMessageFunc(REG(a1,int *arg))
  992. {
  993.    int mode = arg[0], flags = 0;
  994.    ULONG qual = arg[1];
  995.    if (arg[2]) return; // Toolbar qualifier bug work-around
  996.    if (mode == NEW_FORWARD && qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) mode = NEW_BOUNCE;
  997.    if (mode == NEW_FORWARD && qual & IEQUALIFIER_CONTROL) flags = NEWF_FWD_NOATTACH;
  998.    if (mode == NEW_REPLY && qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) flags = NEWF_REP_PRIVATE;
  999.    if (mode == NEW_REPLY && qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT)) flags = NEWF_REP_MLIST;
  1000.    if (mode == NEW_REPLY && qual & IEQUALIFIER_CONTROL) flags = NEWF_REP_NOQUOTE;
  1001.    MA_NewMessage(mode, flags);
  1002. }
  1003. MakeHook(MA_NewMessageHook, MA_NewMessageFunc);
  1004.  
  1005. ///
  1006. /// MA_DeleteMessage
  1007. //  Deletes selected messages
  1008. void MA_DeleteMessage(BOOL delatonce, BOOL force)
  1009. {
  1010.    struct Mail **mlist, *mail;
  1011.    int i, selected;
  1012.    APTR lv = G->MA->GUI.NL_MAILS;
  1013.    char buffer[SIZE_DEFAULT];
  1014.    struct Folder *delfolder = FO_GetFolderByType(FT_DELETED, NULL), *folder = FO_GetCurrentFolder();
  1015.    BOOL ignoreall = FALSE;
  1016.  
  1017.    if (!(mlist = MA_CreateMarkedList(lv))) return;
  1018.    selected = (int)*mlist;
  1019.    if (C->Confirm && selected >= C->ConfirmDelete && !force)
  1020.    {
  1021.       SPrintF(buffer, selected==1 ? GetStr(MSG_MA_1Selected) : GetStr(MSG_MA_xSelected), selected);
  1022.       strcat(buffer, GetStr(MSG_MA_ConfirmDel));
  1023.       if (!MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_OkayCancelReq), buffer))
  1024.       {
  1025.          free(mlist);
  1026.          return;
  1027.       }
  1028.    }
  1029.    set(lv, MUIA_NList_Quiet, TRUE);
  1030.    Busy(GetStr(MSG_BusyDeleting), itoa(selected), 0, selected);
  1031.    if (C->RemoveAtOnce || folder == delfolder) delatonce = TRUE;
  1032.    for (i = 0; i < selected; i++)
  1033.    {
  1034.       Busy(NULL, NULL, i, 0);
  1035.       mail = mlist[i+2];
  1036.       if (mail->Flags & MFLAG_SENDMDN) if ((mail->Status == STATUS_NEW || mail->Status == STATUS_UNR) && !ignoreall) ignoreall = RE_DoMDN(MDN_DELE, mail, TRUE);
  1037.       if (delatonce) MA_DeleteSingle(mail, TRUE);
  1038.       else
  1039.       {
  1040.          struct MailInfo *mi = GetMailInfo(mail);
  1041.          MA_MoveCopySingle(mail, mi->Pos, mail->Folder, delfolder, FALSE);
  1042.       }
  1043.    }
  1044.    BusyEnd;
  1045.    set(lv, MUIA_NList_Quiet, FALSE);
  1046.    free(mlist);
  1047.    if (delatonce)
  1048.       AppendLogNormal(20, GetStr(MSG_LOG_Deleting), (void *)selected, folder->Name, "", "");
  1049.    else
  1050.    {
  1051.       AppendLogNormal(22, GetStr(MSG_LOG_Moving), (void *)selected, folder->Name, delfolder->Name, "");
  1052.       DisplayStatistics(delfolder);
  1053.    }
  1054.    DisplayStatistics(NULL);
  1055.    MA_ChangeSelectedFunc();
  1056. }
  1057.  
  1058. void SAVEDS ASM MA_DeleteMessageFunc(REG(a1,int *arg))
  1059. {
  1060.    BOOL delatonce = arg[0] & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
  1061.    if (arg[1]) return; // Toolbar qualifier bug work-around
  1062.    MA_DeleteMessage(delatonce, FALSE);
  1063. }
  1064. MakeHook(MA_DeleteMessageHook, MA_DeleteMessageFunc);
  1065.  
  1066. ///
  1067. /// MA_DelKey
  1068. //  User pressed DEL key
  1069. void SAVEDS ASM MA_DelKeyFunc(REG(a1,int *arg))
  1070. {
  1071.    APTR obj;
  1072.    get(G->MA->GUI.WI, MUIA_Window_ActiveObject, &obj);
  1073.    if (!obj || obj == MUIV_Window_ActiveObject_None) get(G->MA->GUI.WI, MUIA_Window_DefaultObject, &obj);
  1074.    if (obj == G->MA->GUI.LV_FOLDERS) FO_DeleteFolderFunc();
  1075.    else MA_DeleteMessage(arg[0], FALSE);
  1076. }
  1077. MakeHook(MA_DelKeyHook, MA_DelKeyFunc);
  1078.  
  1079. ///
  1080. /// MA_GetAddressSelect
  1081. //  Asks user which address (from/replyto) to store
  1082. LOCAL struct Person *MA_GetAddressSelect(struct Mail *mail)
  1083. {
  1084.    struct Person *pe = GetReturnAddress(mail);
  1085.    if (C->CompareAddress && *mail->ReplyTo.Address) if (stricmp(mail->From.Address, mail->ReplyTo.Address))
  1086.    {
  1087.       char buffer[SIZE_LARGE];
  1088.       sprintf(buffer, GetStr(MSG_MA_CompareReq), mail->From.Address, mail->ReplyTo.Address);
  1089.       switch (MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_MA_Compare2ReqOpt), buffer))
  1090.       {
  1091.          case 2: pe = &mail->ReplyTo; break;
  1092.          case 1: pe = &mail->From; break;
  1093.          case 0: pe = NULL;
  1094.       }
  1095.    }
  1096.    return pe;
  1097. }
  1098.  
  1099. ///
  1100. /// MA_GetAddress
  1101. //  Stores address from a list of messages to the address book
  1102. void MA_GetAddress(struct Mail **mlist)
  1103. {
  1104.    int i, j, winnum, num = (int)mlist[0], mode = AET_USER;
  1105.    struct Folder *folder = mlist[2]->Folder;
  1106.    BOOL outgoing = folder ? OUTGOING(folder->Type) : FALSE;
  1107.    struct ExtendedMail *email;
  1108.  
  1109.    if (num == 1)
  1110.    {
  1111.       if (outgoing && mlist[2]->Flags & MFLAG_MULTIRCPT) mode = AET_LIST;
  1112.    }
  1113.    else mode = AET_LIST;
  1114.    if (C->UseCManager)
  1115.    {
  1116. /*
  1117.       struct CMUser *user;
  1118.       if (mode == AET_USER) if (user = CM_AllocEntry(CME_USER))
  1119.       {
  1120.          char *p;
  1121.          stccpy(user->Address, pe->Address, 80);
  1122.          stccpy(user->Name, pe->RealName, 80);
  1123.          if (p = strchr(user->Name, ' ')) { *p = 0; stccpy(user->LastName, p, 80); }
  1124.          CM_AddEntry(user);
  1125.          CM_FreeEntry(user);
  1126.       }
  1127. */
  1128.    }
  1129.    else
  1130.    {
  1131.       struct Person *pe = NULL;
  1132.       if (mode == AET_USER)
  1133.       {
  1134.          pe = outgoing ? &(mlist[2]->To) : MA_GetAddressSelect(mlist[2]);
  1135.          if (!pe) return;
  1136.       }
  1137.       DoMethod(G->App, MUIM_CallHook, &AB_OpenHook, ABM_EDIT);
  1138.       if ((winnum = EA_Init(mode, NULL)) >= 0)
  1139.          if (mode == AET_USER)
  1140.          {
  1141.             setstring(G->EA[winnum]->GUI.ST_REALNAME, pe->RealName);
  1142.             setstring(G->EA[winnum]->GUI.ST_ADDRESS, pe->Address);
  1143.          }
  1144.          else
  1145.             for (i = 2; i < num+2; i++)
  1146.             {
  1147.                if (outgoing)
  1148.                {
  1149.                   DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(mlist[i]->To)), MUIV_List_Insert_Bottom);
  1150.                   if ((mlist[i]->Flags & MFLAG_MULTIRCPT)) if ((email = MA_ExamineMail(mlist[i]->Folder, mlist[i]->MailFile, NULL, TRUE)))
  1151.                   {
  1152.                      for (j = 0; j < email->NoSTo; j++) DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(email->STo[j])), MUIV_List_Insert_Bottom);
  1153.                      for (j = 0; j < email->NoCC; j++) DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(&(email->CC[j])), MUIV_List_Insert_Bottom);
  1154.                      MA_FreeEMailStruct(email);
  1155.                   }
  1156.                }
  1157.                else
  1158.                   DoMethod(G->EA[winnum]->GUI.LV_MEMBER, MUIM_List_InsertSingle, BuildAddrName2(GetReturnAddress(mlist[i])), MUIV_List_Insert_Bottom);
  1159.             }
  1160.    }
  1161. }
  1162.  
  1163. ///
  1164. /// MA_GetAddressFunc
  1165. //  Stores addresses from selected messages to the address book
  1166. void SAVEDS MA_GetAddressFunc(void)
  1167. {
  1168.    struct Mail **mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS);
  1169.    if (mlist)
  1170.    {
  1171.       MA_GetAddress(mlist);
  1172.       free(mlist);
  1173.    }
  1174. }
  1175. MakeHook(MA_GetAddressHook, MA_GetAddressFunc);
  1176.  
  1177. ///
  1178. /// MA_PopNow
  1179. //  Fetches new mail from POP3 account(s)
  1180. void MA_PopNow(int mode, int pop)
  1181. {
  1182.    if (G->TR) return; // Don't proceed if another transfer is in progress
  1183.    if (C->UpdateStatus) MA_UpdateStatus();
  1184.    MA_StartMacro(MACRO_PREGET, itoa(mode-POP_USER));
  1185.    TR_GetMailFromNextPOP(TRUE, pop, mode);
  1186. }
  1187.  
  1188. void SAVEDS ASM MA_PopNowFunc(REG(a1,int *arg))
  1189. {
  1190.    ULONG qual = (ULONG)arg[2];
  1191.    if (arg[3]) return; // Toolbar qualifier bug work-around
  1192.    if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) G->TR_Exchange = TRUE;
  1193.    MA_PopNow(arg[0],arg[1]);
  1194. }
  1195. MakeHook(MA_PopNowHook, MA_PopNowFunc);
  1196. ///
  1197.  
  1198. /*** Sub-button functions ***/
  1199. /// MA_AllocRules
  1200. //  Allocates and initializes search structures for filters
  1201. int MA_AllocRules(struct Search **search, int mode)
  1202. {
  1203.    int scnt = 0, i, j, stat;
  1204.    struct Rule *rule;
  1205.  
  1206.    for (i = 0; i < MAXRU; i++) if ((rule = C->RU[i]))
  1207.    {
  1208.       if (mode == APPLY_AUTO && !rule->ApplyToNew) continue;
  1209.       if (mode == APPLY_USER && !rule->ApplyOnReq) continue;
  1210.       if (mode == APPLY_SENT && !rule->ApplyToSent) continue;
  1211.       if (mode == APPLY_REMOTE && !rule->Remote) continue;
  1212.       for (j = 0; j < 2; j++)
  1213.       {
  1214.          search[scnt+j*MAXRU] = malloc(sizeof(struct Search));
  1215.          stat = 0;
  1216.          if (rule->Field[j] == 11) for (; stat < 8; stat++) if (!stricmp(rule->Match[j], Status[stat])) break;
  1217.          FI_PrepareSearch(search[scnt+j*MAXRU], rule->Field[j], rule->CaseSens[j], rule->SubField[j], rule->Comparison[j], stat, rule->Substring[j], rule->Match[j], rule->CustomField[j]);
  1218.          search[scnt+j*MAXRU]->Rule = rule;
  1219.       }
  1220.       scnt++;
  1221.    }
  1222.    return scnt;
  1223. }
  1224.  
  1225. ///
  1226. /// MA_FreeRules
  1227. //  Frees filter search structures
  1228. void MA_FreeRules(struct Search **search, int scnt)
  1229. {
  1230.    int i, j;
  1231.    for (i = 0; i < scnt; i++) for (j = 0; j < 2; j++)
  1232.    {
  1233.       FreeData2D(&(search[i+j*MAXRU]->List));
  1234.       free(search[i+j*MAXRU]);
  1235.    }
  1236. }
  1237.  
  1238. ///
  1239. /// MA_ExecuteRuleAction
  1240. //  Applies filter action to a message
  1241. BOOL MA_ExecuteRuleAction(struct Rule *rule, struct Mail *mail)
  1242. {
  1243.    struct Mail *mlist[3];
  1244.    struct Folder* fo;
  1245.    mlist[0] = (struct Mail *)1; mlist[1] = NULL; mlist[2] = mail;
  1246.    if ((rule->Actions & 1) == 1) if (*rule->BounceTo)
  1247.    {
  1248.       G->RRs.Bounced++;
  1249.       MA_NewBounce(mail, TRUE);
  1250.       setstring(G->WR[2]->GUI.ST_TO, rule->BounceTo);
  1251.       DoMethod(G->App, MUIM_CallHook, &WR_NewMailHook, WRITE_QUEUE, 2);
  1252.    }
  1253.    if ((rule->Actions & 2) == 2) if (*rule->ForwardTo)
  1254.    {
  1255.       G->RRs.Forwarded++;
  1256.       MA_NewForward(mlist, TRUE);
  1257.       setstring(G->WR[2]->GUI.ST_TO, rule->ForwardTo);
  1258.       WR_NewMail(WRITE_QUEUE, 2);
  1259.    }
  1260.    if ((rule->Actions & 4) == 4) if (*rule->ReplyFile)
  1261.    {
  1262.       MA_NewReply(mlist, TRUE);
  1263.       FileToEditor(rule->ReplyFile, G->WR[2]->GUI.TE_EDIT);
  1264.       WR_NewMail(WRITE_QUEUE, 2);
  1265.       G->RRs.Replied++;
  1266.    }
  1267.    if ((rule->Actions & 8) == 8) if (*rule->ExecuteCmd)
  1268.    {
  1269.       char buf[SIZE_COMMAND+SIZE_PATHFILE];
  1270.       strcpy(buf, rule->ExecuteCmd); strcat(buf, " ");
  1271.       strcat(buf, GetMailFile(NULL, NULL, mail));
  1272.       ExecuteCommand(buf, FALSE, NULL);
  1273.       G->RRs.Executed++;
  1274.    }
  1275.    if ((rule->Actions & 16) == 16) if (*rule->PlaySound)
  1276.    {
  1277.       PlaySound(rule->PlaySound);
  1278.    }
  1279.    if ((rule->Actions & 32) == 32) if ((fo = FO_GetFolderByName(rule->MoveTo, NULL))) if (mail->Folder != fo)  // Move
  1280.    {
  1281.       G->RRs.Moved++;
  1282.       if (fo->LoadedMode != 2 && (fo->XPKType&1)) fo->Flags |= FOFL_FREEXS;
  1283.       MA_MoveCopy(mail, mail->Folder, fo, FALSE);
  1284.       return FALSE;
  1285.    }
  1286.    if ((rule->Actions & 64) == 64)
  1287.    {
  1288.       G->RRs.Deleted++;
  1289.       if (mail->Flags & MFLAG_SENDMDN) if (mail->Status == STATUS_NEW || mail->Status == STATUS_UNR) RE_DoMDN(MDN_DELE|MDN_AUTOACT, mail, FALSE);
  1290.       MA_DeleteSingle(mail, FALSE);
  1291.       return FALSE;
  1292.    }
  1293.    return TRUE;
  1294. }
  1295.  
  1296. ///
  1297. /// MA_ApplyRulesFunc
  1298. //  Apply filters
  1299. void SAVEDS ASM MA_ApplyRulesFunc(REG(a1,int *arg))
  1300. {
  1301.    struct Mail *mail, **mlist = NULL;
  1302.    struct Folder *folder;
  1303.    int m, i, mode = arg[0], scnt, matches = 0, minselected = (arg[1] & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) ? 1 : 2;
  1304.    struct Search *search[2*MAXRU];
  1305.    APTR lv = G->MA->GUI.NL_MAILS;
  1306.    char buf[SIZE_LARGE];
  1307.  
  1308.    if (arg[2]) return; // Toolbar qualifier bug work-around
  1309.    folder = (mode == APPLY_AUTO) ? FO_GetFolderByType(FT_INCOMING, NULL) : FO_GetCurrentFolder();
  1310.    if (mode == APPLY_USER && folder->Type != FT_INCOMING)
  1311.    {
  1312.       sprintf(buf, GetStr(MSG_MA_ConfirmFilter), folder->Name);
  1313.       if (!MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ConfirmReq), GetStr(MSG_YesNoReq), buf)) return;
  1314.    }
  1315.    clear(&G->RRs, sizeof(struct RuleResult));
  1316.    set(lv, MUIA_NList_Quiet, TRUE); G->AppIconQuiet = TRUE;
  1317.    if ((scnt = MA_AllocRules(search, mode)))
  1318.    {
  1319.       if (mode == APPLY_USER || mode == APPLY_RX || mode == APPLY_RX_ALL) if ((mlist = MA_CreateMarkedList(lv))) if ((int)mlist[0] < minselected) { free(mlist); mlist = NULL; }
  1320.       if (!mlist) mlist = MA_CreateFullList(folder);
  1321.       if (mlist)
  1322.       {
  1323.          Busy(GetStr(MSG_BusyFiltering), "", 0, (int)*mlist);
  1324.          for (m = 0; m < (int)*mlist; m++)
  1325.          {
  1326.             mail = mlist[m+2];
  1327.             if ((mode == APPLY_AUTO || mode == APPLY_RX) && mail->Status != STATUS_NEW) continue;
  1328.             G->RRs.Checked++;
  1329.             for (i = 0; i < scnt; i++)
  1330.             {
  1331.                DoMethod(G->App, MUIM_Application_InputBuffered);
  1332.                if (FI_DoComplexSearch(search[i], search[i]->Rule->Combine, search[i+MAXRU], mail))
  1333.                {
  1334.                   matches++;
  1335.                   if (!MA_ExecuteRuleAction(search[i]->Rule, mail)) break;
  1336.                }
  1337.             }
  1338.             Busy(NULL, NULL, m, 0);
  1339.          }
  1340.          free(mlist);
  1341.          if (G->RRs.Moved) MA_FlushIndexes(FALSE);
  1342.          if (G->RRs.Checked) AppendLog(26, GetStr(MSG_LOG_Filtering), (void *)(G->RRs.Checked), folder->Name, (void *)matches, "");
  1343.          Busy("", NULL,  0, 0);
  1344.       }
  1345.       MA_FreeRules(search, scnt);
  1346.    }
  1347.    set(lv, MUIA_NList_Quiet, FALSE); G->AppIconQuiet = FALSE;
  1348.    DisplayStatistics(NULL);
  1349.    if (G->RRs.Checked && mode == APPLY_USER)
  1350.    {
  1351.       sprintf(buf, GetStr(MSG_MA_FilterStats), G->RRs.Checked, G->RRs.Forwarded, G->RRs.Moved, G->RRs.Deleted);
  1352.       MUI_Request(G->App, G->MA->GUI.WI, 0, NULL, GetStr(MSG_OkayReq), buf);
  1353.    }
  1354. }
  1355. MakeHook(MA_ApplyRulesHook, MA_ApplyRulesFunc);
  1356.  
  1357. ///
  1358. /// MA_SendMList
  1359. //  Sends a list of messages
  1360. BOOL MA_SendMList(struct Mail **mlist)
  1361. {
  1362.    BOOL success = FALSE;
  1363.    MA_StartMacro(MACRO_PRESEND, NULL);
  1364.    if (TR_OpenTCPIP())
  1365.    {
  1366.       if (CO_IsValid()) if ((G->TR = TR_New(TR_SEND)))
  1367.       {
  1368.          if (SafeOpenWindow(G->TR->GUI.WI)) success = TR_ProcessSEND(mlist);
  1369.          else { MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1370.       }
  1371.       TR_CloseTCPIP();
  1372.    }
  1373.    else ER_NewError(GetStr(MSG_ER_NoTCP), NULL, NULL);
  1374.    MA_StartMacro(MACRO_POSTSEND, NULL);
  1375.    return success;
  1376. }
  1377.  
  1378. ///
  1379. /// MA_Send
  1380. //  Sends selected or all messages
  1381. BOOL MA_Send(int sendpos)
  1382. {
  1383.    struct Mail **mlist;
  1384.    APTR lv = G->MA->GUI.NL_MAILS;
  1385.    BOOL success = FALSE;
  1386.    if (!G->TR)
  1387.    {
  1388.       MA_ChangeFolder(FO_GetFolderByType(FT_OUTGOING, NULL));
  1389.       if (sendpos == SEND_ALL) DoMethod(lv, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_On, NULL);
  1390.       if ((mlist = MA_CreateMarkedList(lv)))
  1391.       {
  1392.          success = MA_SendMList(mlist);
  1393.          free(mlist);
  1394.       }
  1395.    }
  1396.    return success;
  1397. }
  1398.  
  1399. void SAVEDS ASM MA_SendFunc(REG(a1,int *arg))
  1400. {
  1401.    MA_Send(arg[0]);
  1402. }
  1403. MakeHook(MA_SendHook, MA_SendFunc);
  1404. ///
  1405.  
  1406. /*** Menu options ***/
  1407. /// MA_SetStatusTo
  1408. //  Sets status of selectes messages
  1409. void MA_SetStatusTo(int status)
  1410. {
  1411.    APTR lv = G->MA->GUI.NL_MAILS;
  1412.    struct Mail **mlist;
  1413.  
  1414.    if ((mlist = MA_CreateMarkedList(lv)))
  1415.    {
  1416.       int i;
  1417.       set(lv, MUIA_NList_Quiet, TRUE);
  1418.       for (i = 0; i < (int)*mlist; i++) if (mlist[i+2]->Status != status) MA_SetMailStatus(mlist[i+2], status);
  1419.       set(lv, MUIA_NList_Quiet, FALSE);
  1420.       free(mlist);
  1421.       DisplayStatistics(NULL);
  1422.    }
  1423. }
  1424.  
  1425. void SAVEDS ASM MA_SetStatusToFunc(REG(a1,int *arg))
  1426. {
  1427.    MA_SetStatusTo(*arg);
  1428. }
  1429. MakeHook(MA_SetStatusToHook, MA_SetStatusToFunc);
  1430.  
  1431. ///
  1432. /// MA_SelectAllFunc
  1433. //  Selects all messages
  1434. void SAVEDS MA_SelectAllFunc(void)
  1435. {
  1436.    DoMethod(G->MA->GUI.NL_MAILS, MUIM_NList_Select, MUIV_NList_Select_All, MUIV_NList_Select_On, NULL);
  1437. }
  1438. MakeHook(MA_SelectAllHook, MA_SelectAllFunc);
  1439.  
  1440. ///
  1441. /// MA_DeleteOldFunc
  1442. //  Deletes old messages
  1443. void SAVEDS MA_DeleteOldFunc(void)
  1444. {
  1445.    struct Folder **flist;
  1446.    struct DateStamp today;
  1447.    long today_days;
  1448.    int f;
  1449.    struct Mail *mail, *next;
  1450.  
  1451.    Busy(GetStr(MSG_BusyDeletingOld), "", 0, 0);
  1452.    DateStamp(&today); today_days = today.ds_Days;
  1453.    if ((flist = FO_CreateList()))
  1454.    {
  1455.       for (f = 1; f <= (int)*flist; f++) if (flist[f]->MaxAge) if (MA_GetIndex(flist[f]))
  1456.          for (mail = flist[f]->Messages; mail; mail = next)
  1457.          {
  1458.             next = mail->Next;
  1459.             today.ds_Days = today_days - flist[f]->MaxAge;
  1460.             if (CompareDates(&today, &(mail->Date)) < 0)
  1461.                if (flist[f]->Type == FT_DELETED || (mail->Status != STATUS_NEW && mail->Status != STATUS_UNR))
  1462.                   MA_DeleteSingle(mail, C->RemoveOnQuit);
  1463.          }
  1464.       free(flist);
  1465.    }
  1466.    BusyEnd;
  1467. }
  1468. MakeHook(MA_DeleteOldHook, MA_DeleteOldFunc);
  1469.  
  1470. ///
  1471. /// MA_DeleteDeletedFunc
  1472. //  Removes messages from 'deleted' folder
  1473. void SAVEDS MA_DeleteDeletedFunc(void)
  1474. {       
  1475.    int i = 0;
  1476.    struct Mail *mail;
  1477.    struct Folder *folder = FO_GetFolderByType(FT_DELETED, NULL);
  1478.  
  1479.    Busy(GetStr(MSG_BusyEmptyingTrash), "", 0, folder->Total);
  1480.    for (mail = folder->Messages; mail; mail = mail->Next)
  1481.    {
  1482.       Busy(NULL, NULL, i++, 0);
  1483.       AppendLogVerbose(21, GetStr(MSG_LOG_DeletingVerbose), AddrName(mail->From), mail->Subject, folder->Name, "");
  1484.       DeleteFile(GetMailFile(NULL, NULL, mail));
  1485.    }
  1486.    ClearMailList(folder, TRUE);
  1487.    MA_ExpireIndex(folder);
  1488.    if (FO_GetCurrentFolder() == folder) DisplayMailList(folder, G->MA->GUI.NL_MAILS);
  1489.    if (i) AppendLogNormal(20, GetStr(MSG_LOG_Deleting), (void *)i, folder->Name, "", "");
  1490.    DisplayStatistics(folder);
  1491.    BusyEnd;
  1492. }            
  1493. MakeHook(MA_DeleteDeletedHook, MA_DeleteDeletedFunc);
  1494.  
  1495. ///
  1496. /// MA_RescanIndexFunc
  1497. //  Updates index of current folder
  1498. void SAVEDS MA_RescanIndexFunc(void)
  1499. {
  1500.    struct Folder *folder = FO_GetCurrentFolder();
  1501.  
  1502.    MA_ScanMailBox(folder);
  1503.    MA_SaveIndex(folder);
  1504.    MA_ChangeFolder(NULL);
  1505. }
  1506. MakeHook(MA_RescanIndexHook, MA_RescanIndexFunc);
  1507.  
  1508. ///
  1509. /// MA_ExportMessages
  1510. //  Saves messages to a UUCP mailbox file
  1511. BOOL MA_ExportMessages(BOOL all, char *filename, BOOL append)
  1512. {
  1513.    BOOL success = FALSE;
  1514.    char outname[SIZE_PATHFILE];
  1515.    struct Mail **mlist;
  1516.    if (all) mlist = MA_CreateFullList(FO_GetCurrentFolder());
  1517.    else mlist = MA_CreateMarkedList(G->MA->GUI.NL_MAILS);
  1518.    if (mlist)
  1519.    {
  1520.       if (!filename) if (ReqFile(ASL_IMPORT, G->MA->GUI.WI, GetStr(MSG_MA_ExportMessages), 1, C->DetachDir, ""))
  1521.       {
  1522.          strmfp(filename = outname, G->ASLReq[ASL_IMPORT]->fr_Drawer, G->ASLReq[ASL_IMPORT]->fr_File);
  1523.          if (FileExists(filename))
  1524.          {
  1525.             switch (MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_ExportMessages), GetStr(MSG_MA_ExportAppendOpts), GetStr(MSG_MA_ExportAppendReq)))
  1526.             {
  1527.                case 1: append = FALSE; break;
  1528.                case 2: append = TRUE; break;
  1529.                case 0: filename = NULL;
  1530.             }
  1531.          }
  1532.       }
  1533.       if (filename) if ((G->TR = TR_New(TR_EXPORT)))
  1534.       {
  1535.          if (SafeOpenWindow(G->TR->GUI.WI)) success = TR_ProcessEXPORT(filename, mlist, append);
  1536.          else {  MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1537.       }
  1538.       free(mlist);
  1539.    }
  1540.    return success;
  1541. }
  1542.  
  1543. void SAVEDS ASM MA_ExportMessagesFunc(REG(a1,int *arg))
  1544. {
  1545.    MA_ExportMessages((BOOL)*arg, NULL, FALSE);
  1546. }
  1547. MakeHook(MA_ExportMessagesHook, MA_ExportMessagesFunc);
  1548.  
  1549. ///
  1550. /// MA_ImportMessages
  1551. //  Imports messages from a UUCP mailbox file
  1552. BOOL MA_ImportMessages(char *fname)
  1553. {
  1554.    FILE *fh;
  1555.  
  1556.    if ((fh = fopen(fname, "r")))
  1557.    {
  1558.       if ((G->TR = TR_New(TR_IMPORT)))
  1559.       {
  1560.          stccpy(G->TR->ImportFile, fname, SIZE_PATHFILE);
  1561.          TR_SetWinTitle(TRUE, FilePart(fname));
  1562.          G->TR->ImportBox = FO_GetCurrentFolder();
  1563.          if (SafeOpenWindow(G->TR->GUI.WI))
  1564.          {
  1565.             TR_GetMessageList_IMPORT(fh);
  1566.             fclose(fh);
  1567.             return TRUE;
  1568.          }
  1569.          else { MA_ChangeTransfer(TRUE); DisposeModulePush(&G->TR); }
  1570.       }
  1571.       fclose(fh);
  1572.    }
  1573.    return FALSE;
  1574. }
  1575.  
  1576. void SAVEDS MA_ImportMessagesFunc(void)
  1577. {
  1578.    if (ReqFile(ASL_IMPORT, G->MA->GUI.WI, GetStr(MSG_MA_ImportMessages), 0, C->DetachDir, ""))
  1579.    {
  1580.       char inname[SIZE_PATHFILE];
  1581.       strmfp(inname, G->ASLReq[ASL_IMPORT]->fr_Drawer, G->ASLReq[ASL_IMPORT]->fr_File);
  1582.       MA_ImportMessages(inname);
  1583.    }
  1584. }
  1585. MakeHook(MA_ImportMessagesHook, MA_ImportMessagesFunc);
  1586.  
  1587. ///
  1588. /// MA_MoveMessageFunc
  1589. //  Moves selected messages to a user specified folder
  1590. void SAVEDS MA_MoveMessageFunc(void)
  1591. {
  1592.    struct Folder *src = FO_GetCurrentFolder(), *dst;
  1593.    if ((dst = FolderRequest(GetStr(MSG_MA_MoveMsg), GetStr(MSG_MA_MoveMsgReq), GetStr(MSG_MA_MoveGad), GetStr(MSG_Cancel), src, G->MA->GUI.WI)))
  1594.       MA_MoveCopy(NULL, src, dst, FALSE);
  1595. }
  1596. MakeHook(MA_MoveMessageHook, MA_MoveMessageFunc);
  1597.  
  1598. ///
  1599. /// MA_CopyMessageFunc
  1600. //  Copies selected messages to a user specified folder
  1601. void SAVEDS MA_CopyMessageFunc(void)
  1602. {
  1603.    struct Folder *src = FO_GetCurrentFolder(), *dst;
  1604.    if ((dst = FolderRequest(GetStr(MSG_MA_CopyMsg), GetStr(MSG_MA_MoveMsgReq), GetStr(MSG_MA_CopyGad), GetStr(MSG_Cancel), NULL, G->MA->GUI.WI)))
  1605.       MA_MoveCopy(NULL, src, dst, TRUE);
  1606. }
  1607. MakeHook(MA_CopyMessageHook, MA_CopyMessageFunc);
  1608.  
  1609. ///
  1610. /// MA_ChangeSubject
  1611. //  Changes subject of a message
  1612. void MA_ChangeSubject(struct Mail *mail, char *subj)
  1613. {
  1614.    struct Folder *fo = mail->Folder;
  1615.    int f;
  1616.    FILE *oldfh, *newfh;
  1617.    char *oldfile, newfile[SIZE_PATHFILE], fullfile[SIZE_PATHFILE], buf[SIZE_LINE];
  1618.  
  1619.    if (!strcmp(subj, mail->Subject)) return;
  1620.    if (!StartUnpack(oldfile = GetMailFile(NULL, NULL, mail), fullfile, fo)) return;
  1621.    strmfp(newfile, GetFolderDir(fo), "00000.tmp");
  1622.    if ((newfh = fopen(newfile, "w")))
  1623.    {
  1624.       if ((oldfh = fopen(fullfile, "r")))
  1625.       {
  1626.          BOOL infield = FALSE, inbody = FALSE, hasorigsubj = FALSE;
  1627.          while (fgets(buf, SIZE_LINE, oldfh))
  1628.          {
  1629.             if (*buf == '\n' && !inbody)
  1630.             {
  1631.                inbody = TRUE;
  1632.                if (!hasorigsubj) EmitHeader(newfh, "X-Original-Subject", mail->Subject);
  1633.                EmitHeader(newfh, "Subject", subj);
  1634.             }
  1635.             if (!ISpace(*buf))
  1636.             {
  1637.                infield = !strnicmp(buf, "subject:", 8);
  1638.                if (!strnicmp(buf, "x-original-subject:", 19)) hasorigsubj = TRUE;
  1639.             }
  1640.             if (!infield || inbody) fputs(buf, newfh);
  1641.          }
  1642.          fclose(oldfh);
  1643.          DeleteFile(oldfile);
  1644.       }
  1645.       fclose(newfh);
  1646.       f = FileSize(newfile); fo->Size += f - mail->Size; mail->Size = f;
  1647.       AppendLog(82, GetStr(MSG_LOG_ChangingSubject), mail->Subject, mail->MailFile, fo->Name, subj);
  1648.       strcpy(mail->Subject, subj);
  1649.       MA_ExpireIndex(fo);
  1650.       if (fo->XPKType > 1) DoPack(newfile, oldfile, fo);
  1651.       else RenameFile(newfile, oldfile);
  1652.       MA_SetMailStatus(mail, mail->Status);
  1653.    }
  1654.    FinishUnpack(fullfile);
  1655. }
  1656.  
  1657. ///
  1658. /// MA_ChangeSubjectFunc
  1659. //  Changes subject of selected messages
  1660. void SAVEDS MA_ChangeSubjectFunc(void)
  1661. {
  1662.    struct Mail **mlist, *mail;
  1663.    int i, selected;
  1664.    BOOL ask = TRUE;
  1665.    APTR lv = G->MA->GUI.NL_MAILS;
  1666.    char subj[SIZE_SUBJECT];
  1667.  
  1668.    if (!(mlist = MA_CreateMarkedList(lv))) return;
  1669.    selected = (int)*mlist;
  1670.    for (i = 0; i < selected; i++)
  1671.    {
  1672.       mail = mlist[i+2];
  1673.       if (ask)
  1674.       {
  1675.          strcpy(subj, mail->Subject);
  1676.          switch (StringRequest(subj, SIZE_SUBJECT, GetStr(MSG_MA_ChangeSubj), GetStr(MSG_MA_ChangeSubjReq), GetStr(MSG_Okay), (i || selected == 1) ? NULL : GetStr(MSG_MA_All), GetStr(MSG_Cancel), FALSE, G->MA->GUI.WI))
  1677.          {
  1678.             case 0: free(mlist); return;
  1679.             case 2: ask = FALSE;
  1680.          }
  1681.       }
  1682.       MA_ChangeSubject(mail, subj);
  1683.    }
  1684.    free(mlist);
  1685.    DoMethod(lv, MUIM_NList_Redraw, MUIV_NList_Redraw_All);
  1686.    DisplayStatistics(NULL);
  1687. }
  1688. MakeHook(MA_ChangeSubjectHook, MA_ChangeSubjectFunc);
  1689.  
  1690. ///
  1691. /// MA_AboutMUIFunc
  1692. //  Displays 'About MUI' window
  1693. void SAVEDS MA_AboutMUIFunc(void)
  1694. {
  1695.    static APTR muiwin = NULL;
  1696.  
  1697.    if (!muiwin) muiwin = AboutmuiObject,
  1698.       MUIA_Window_RefWindow, G->MA->GUI.WI,
  1699.       MUIA_Aboutmui_Application, G->App,
  1700.    End;
  1701.    if (muiwin) SafeOpenWindow(muiwin); else DisplayBeep(0);
  1702. }
  1703. MakeHook(MA_AboutMUIHook, MA_AboutMUIFunc);
  1704.  
  1705. ///
  1706. /// MA_CheckVersionFunc
  1707. //  Checks YAM homepage for new program versions
  1708. void SAVEDS MA_CheckVersionFunc(void)
  1709. {
  1710.    struct TempFile *tf;
  1711.    int mon, day, year;
  1712.    long thisver, currver;
  1713.    char newver[SIZE_SMALL], buf[SIZE_LARGE];
  1714.  
  1715.    if (TR_OpenTCPIP())
  1716.    {
  1717.       sscanf(__YAM_VERDATE, "%ld.%ld.%ld", &day, &mon, &year);
  1718.       thisver = (year<78 ? 1000000:0)+year*10000+mon*100+day;
  1719.       Busy(GetStr(MSG_BusyGettingVerInfo), "", 0, 0);
  1720.       tf = OpenTempFile(NULL);
  1721.       if (TR_DownloadURL(C->SupportSite, "files/", "version", tf->Filename))
  1722.       {
  1723.          if ((tf->FP = fopen(tf->Filename,"r")))
  1724.          {
  1725.             fscanf(tf->FP, "%ld.%ld.%ld", &day, &mon, &year);
  1726.             GetLine(tf->FP, newver, SIZE_SMALL);
  1727.             currver = (year<78 ? 1000000:0)+year*10000+mon*100+day;
  1728.             sprintf(buf, GetStr(MSG_MA_LatestVersion), &newver[1], day, mon, year, __YAM_VERSION, __YAM_VERDATE,
  1729.                currver > thisver ? GetStr(MSG_MA_NewVersion) : GetStr(MSG_MA_NoNewVersion));
  1730.             if (MUI_Request(G->App, G->MA->GUI.WI, 0, GetStr(MSG_MA_CheckVersion), GetStr(MSG_MA_VersionReqOpt), buf)) GotoURL(C->SupportSite);
  1731.          }
  1732.          else ER_NewError(GetStr(MSG_ER_CantOpenTempfile), tf->Filename, NULL);
  1733.       }
  1734.       CloseTempFile(tf);
  1735.       BusyEnd;
  1736.       TR_CloseTCPIP();
  1737.    }
  1738.    else ER_NewError(GetStr(MSG_ER_NoTCP), NULL, NULL);
  1739. }
  1740. MakeHook(MA_CheckVersionHook, MA_CheckVersionFunc);
  1741.  
  1742. ///
  1743. /// MA_ShowErrorsFunc
  1744. //  Opens error message window
  1745. void SAVEDS MA_ShowErrorsFunc(void)
  1746. {
  1747.    ER_NewError(NULL, NULL, NULL);
  1748. }
  1749. MakeHook(MA_ShowErrorsHook, MA_ShowErrorsFunc);
  1750.  
  1751. ///
  1752. /// MA_StartMacro
  1753. //  Launches user-defined ARexx script or AmigaDOS command
  1754. BOOL MA_StartMacro(int num, char *param)
  1755. {
  1756.    BPTR fh;
  1757.    char command[SIZE_LARGE], *wtitle = "CON:////YAM ARexx Window/AUTO";
  1758.    struct RexxMsg *sentrm;
  1759.  
  1760.    strcpy(command, C->RX[num].Script);
  1761.    if (!*command) return 0;
  1762.    if (param) { strcat(command, " "); strcat(command, param); }
  1763.    if (C->RX[num].IsAmigaDOS)
  1764.    {
  1765.       Busy(" ", "", 0, 0);
  1766.       ExecuteCommand(command, !C->RX[num].WaitTerm, C->RX[num].UseConsole ? NULL : OUT_NIL);
  1767.       BusyEnd;
  1768.    }
  1769.    else
  1770.    {
  1771.       if (!(fh = Open(C->RX[num].UseConsole ? wtitle : "NIL:", MODE_NEWFILE)))
  1772.       {
  1773.          ER_NewError(GetStr(MSG_ER_ErrorConsole), NULL, NULL);
  1774.          return FALSE;
  1775.       }
  1776.       if (!(sentrm = SendRexxCommand(G->RexxHost, command, fh)))
  1777.       {
  1778.          Close(fh);
  1779.          ER_NewError(GetStr(MSG_ER_ErrorARexxScript), command, NULL);
  1780.          return FALSE;
  1781.       }
  1782.       if (C->RX[num].WaitTerm)
  1783.       {
  1784.          extern void DoRXCommand( struct RexxHost *, struct RexxMsg *);
  1785.          struct RexxMsg *rm;
  1786.          BOOL waiting = TRUE;
  1787.          Busy(" ", "", 0, 0);
  1788.          do
  1789.          {
  1790.             WaitPort(G->RexxHost->port);
  1791.             while ((rm = (struct RexxMsg *)GetMsg(G->RexxHost->port)))
  1792.             {
  1793.                if ((rm->rm_Action & RXCODEMASK) != RXCOMM) ReplyMsg((struct Message *)rm);
  1794.                else if (rm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
  1795.                {
  1796.                   struct RexxMsg *org = (struct RexxMsg *)rm->rm_Args[15];
  1797.                   if (org)
  1798.                   {
  1799.                      if (rm->rm_Result1) ReplyRexxCommand(org, 20, ERROR_NOT_IMPLEMENTED, NULL);
  1800.                      else ReplyRexxCommand(org, 0, 0, (char *)rm->rm_Result2);
  1801.                   }
  1802.                   if (rm == sentrm) waiting = FALSE;
  1803.                   FreeRexxCommand(rm);
  1804.                   --G->RexxHost->replies;
  1805.                }
  1806.                else if (rm->rm_Args[0]) DoRXCommand(G->RexxHost, rm);
  1807.                else ReplyMsg((struct Message *)rm);
  1808.             }
  1809.          }
  1810.          while (waiting);
  1811.          BusyEnd;
  1812.       }
  1813.    }
  1814.    return TRUE;
  1815. }
  1816.  
  1817. ///
  1818. /// MA_CallRexxFunc
  1819. //  Launches a script from the ARexx menu
  1820. void SAVEDS ASM MA_CallRexxFunc(REG(a1,int *arg))
  1821. {
  1822.    char scname[SIZE_COMMAND];
  1823.    int script = *arg;
  1824.    if (script >= 0)
  1825.    {                 
  1826.       MA_StartMacro(MACRO_MEN0+script, NULL);
  1827.    }
  1828.    else
  1829.    {
  1830.       strmfp(scname, G->ProgDir, "rexx");
  1831.       if (ReqFile(ASL_REXX, G->MA->GUI.WI, GetStr(MSG_MA_ExecuteScript), 0, scname, ""))
  1832.       {
  1833.          strmfp(scname, G->ASLReq[ASL_REXX]->fr_Drawer, G->ASLReq[ASL_REXX]->fr_File);
  1834.          SendRexxCommand(G->RexxHost, scname, NULL);
  1835.       }
  1836.    }
  1837. }
  1838. MakeHook(MA_CallRexxHook, MA_CallRexxFunc);
  1839. ///
  1840.  
  1841. /*** Hooks ***/
  1842. /// PO_Window
  1843. //  Window hook for popup objects
  1844. void SAVEDS ASM PO_Window(REG(a2,Object *pop), REG(a1,Object *win))
  1845. {
  1846.    set(win, MUIA_Window_DefaultObject, pop);
  1847. }
  1848. MakeHook(PO_WindowHook, PO_Window);
  1849.  
  1850. ///
  1851. /// MA_LV_FConFunc
  1852. //  Folder listview construction hook
  1853. struct Folder * SAVEDS ASM MA_LV_FConFunc(REG(a1,struct Folder *fo))
  1854. {
  1855.    struct Folder *entry = malloc(sizeof(struct Folder));
  1856.    memcpy(entry, fo, sizeof(struct Folder));
  1857.    return entry;
  1858. }
  1859. MakeHook(MA_LV_FConHook, MA_LV_FConFunc);
  1860.  
  1861. ///
  1862. /// MA_LV_DspFunc
  1863. //  Message listview display hook
  1864. long SAVEDS ASM MA_LV_DspFunc(REG(a0,struct Hook *hook), REG(a2,char **array), REG(a1,struct Mail *entry))
  1865. {
  1866.    BOOL outbox;
  1867.    struct Folder *folder = NULL;
  1868.    int type = 0;
  1869.  
  1870.   if (G->MA) if ((folder = FO_GetCurrentFolder())) type = folder->Type;
  1871.    outbox = OUTGOING(type);
  1872.    if (entry)
  1873.    {
  1874.       if (folder)
  1875.       {
  1876.          static char dispfro[SIZE_DEFAULT], dispsta[SIZE_DEFAULT], dispsiz[SIZE_SMALL];
  1877.          struct Person *pe;
  1878.          sprintf(array[0] = dispsta, "\033o[%ld]", entry->Status);
  1879.          if (entry->Importance == 1) strcat(dispsta, "\033o[12]");
  1880.          if (entry->Flags & MFLAG_CRYPT) strcat(dispsta, "\033o[15]");
  1881.          else if (entry->Flags & MFLAG_SIGNED) strcat(dispsta, "\033o[16]");
  1882.          else if (entry->Flags & MFLAG_REPORT) strcat(dispsta, "\033o[14]");
  1883.          else if (entry->Flags & MFLAG_MULTIPART) strcat(dispsta, "\033o[13]");
  1884.          array[1] = dispfro; *dispfro = 0;
  1885.          if (entry->Flags & MFLAG_MULTIRCPT) strcat(dispfro, "\033o[11]");
  1886.          pe = outbox ? &entry->To : &entry->From;
  1887.          if (type == FT_CUSTOMMIXED || type == FT_DELETED) if (!stricmp(pe->Address, C->EmailAddress))
  1888.          {
  1889.             pe = &entry->To; strcat(dispfro, GetStr(MSG_MA_ToPrefix));
  1890.          }
  1891.          strncat(dispfro, AddrName((*pe)), SIZE_DEFAULT-strlen(dispfro)-1);
  1892.          array[2] = AddrName((entry->ReplyTo));
  1893.          array[3] = entry->Subject;
  1894.          array[4] = DateStamp2String(&entry->Date, C->SwatchBeat ? DSS_DATEBEAT : DSS_DATETIME);
  1895.          array[5] = dispsiz; *dispsiz = 0;
  1896.          FormatSize(entry->Size, dispsiz);
  1897.          array[6] = entry->MailFile;
  1898.          array[7] = entry->Folder->Name;
  1899.       }
  1900.    }
  1901.    else
  1902.    {
  1903.       array[0] = GetStr(MSG_MA_TitleStatus);
  1904.       array[1] = GetStr(outbox ? MSG_To : MSG_From);
  1905.       array[2] = GetStr(MSG_ReturnAddress);
  1906.       array[3] = GetStr(MSG_Subject);
  1907.       array[4] = GetStr(MSG_Date);
  1908.       array[5] = GetStr(MSG_Size);
  1909.       array[6] = GetStr(MSG_Filename);
  1910.       array[7] = GetStr(MSG_Folder);
  1911.    }
  1912.    return 0;
  1913. }
  1914. MakeHook(MA_LV_DspFuncHook,MA_LV_DspFunc);
  1915.  
  1916. ///
  1917. /// MA_GetRealSubject
  1918. //  Strips reply prefix / mailing list name from subject
  1919. LOCAL char *MA_GetRealSubject(char *sub)
  1920. {
  1921.    char *p, *pend = &sub[strlen(sub)];
  1922.    if (strlen(sub) < 3) return sub;
  1923.    if (sub[2] == ':' && !sub[3]) return "";
  1924.    if (sub[0] == '[') if ((p = strchr(sub, ']'))) if (p < pend-3 && p < &sub[20]) return MA_GetRealSubject(p+2);
  1925.    if (strchr(":[({", sub[2])) if ((p = strchr(sub, ':'))) return MA_GetRealSubject(TrimStart(++p));
  1926.    return sub;
  1927. }
  1928.  
  1929. ///
  1930. /// MA_MailCompare
  1931. //  Compares two messages
  1932. LOCAL int MA_MailCompare(struct Mail *entry1, struct Mail *entry2, int column)
  1933. {
  1934.    static int values[9] = { 50, 35, 30, 25, 45, 60, 40, 20, 55 };
  1935.    switch (column)
  1936.    {
  1937.       case 0: return -(values[entry1->Status]+entry1->Importance)+(values[entry2->Status]+entry2->Importance);
  1938.       case 1: if (OUTGOING(entry1->Folder->Type))
  1939.                  return stricmp(*entry1->To.RealName ? entry1->To.RealName : entry1->To.Address,
  1940.                                 *entry2->To.RealName ? entry2->To.RealName : entry2->To.Address);
  1941.               else
  1942.                  return stricmp(*entry1->From.RealName ? entry1->From.RealName : entry1->From.Address,
  1943.                                 *entry2->From.RealName ? entry2->From.RealName : entry2->From.Address);
  1944.       case 2: return stricmp(*entry1->ReplyTo.RealName ? entry1->ReplyTo.RealName : entry1->ReplyTo.Address,
  1945.                              *entry2->ReplyTo.RealName ? entry2->ReplyTo.RealName : entry2->ReplyTo.Address);
  1946.       case 3: return stricmp(MA_GetRealSubject(entry1->Subject), MA_GetRealSubject(entry2->Subject));
  1947.       case 4: return CompareDates(&entry2->Date, &entry1->Date);
  1948.       case 5: return entry1->Size-entry2->Size;
  1949.       case 6: return strcmp(entry1->MailFile, entry2->MailFile);
  1950.       case 7: return stricmp(entry1->Folder->Name, entry2->Folder->Name);
  1951.    }
  1952.    return 0;
  1953. }
  1954.  
  1955. ///
  1956. /// MA_LV_Cmp2Func
  1957. //  Message listview sort hook
  1958. long SAVEDS ASM MA_LV_Cmp2Func(REG(a1,struct NList_CompareMessage *ncm), REG(a2,Object *obj))
  1959. {
  1960.    struct Mail *entry1 = (struct Mail *)ncm->entry1;
  1961.    struct Mail *entry2 = (struct Mail *)ncm->entry2;
  1962.    long col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  1963.    long col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  1964.    int cmp;
  1965.  
  1966.    if (ncm->sort_type == MUIV_NList_SortType_None) return 0;
  1967.    if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) cmp = MA_MailCompare(entry2, entry1, col1);
  1968.    else                                                cmp = MA_MailCompare(entry1, entry2, col1);
  1969.    if (cmp || col1 == col2) return cmp;
  1970.    if (ncm->sort_type2 & MUIV_NList_TitleMark2_TypeMask) cmp = MA_MailCompare(entry2, entry1, col2);
  1971.    else                                                  cmp = MA_MailCompare(entry1, entry2, col2);
  1972.    return cmp;
  1973. }
  1974. MakeHook(MA_LV_Cmp2Hook, MA_LV_Cmp2Func);
  1975.  
  1976. ///
  1977. /// MA_LV_FCmp2Func
  1978. //  Folder listview sort hook
  1979. long SAVEDS ASM MA_LV_FCmp2Func(REG(a1,struct NList_CompareMessage *ncm), REG(a2,Object *obj))
  1980. {
  1981.    struct Folder *entry1 = (struct Folder *)ncm->entry1;
  1982.    struct Folder *entry2 = (struct Folder *)ncm->entry2;
  1983.    int cmp = 0;
  1984.  
  1985.    if (ncm->sort_type != MUIV_NList_SortType_None)
  1986.    {
  1987.       switch (ncm->sort_type & MUIV_NList_TitleMark_ColMask)
  1988.       {
  1989.          case 0:  cmp = stricmp(entry1->Name, entry2->Name); break;
  1990.          case 1:  cmp = entry1->Total-entry2->Total; break;
  1991.          case 2:  cmp = entry1->Unread-entry2->Unread; break;
  1992.          case 3:  cmp = entry1->New-entry2->New; break;
  1993.          case 4:  cmp = entry1->Size-entry2->Size; break;
  1994.          case 10: return entry1->SortIndex-entry2->SortIndex;
  1995.       }
  1996.       if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask) cmp = -cmp;
  1997.    }
  1998.    return cmp;
  1999. }
  2000. MakeHook(MA_LV_FCmp2Hook, MA_LV_FCmp2Func);
  2001. ///
  2002.  
  2003. /*** GUI ***/
  2004. enum { MMEN_ABOUT=1,MMEN_ABOUTMUI,MMEN_VERSION,MMEN_ERRORS,MMEN_LOGIN,MMEN_HIDE,MMEN_QUIT,
  2005.        MMEN_NEWF,MMEN_NEWS,MMEN_EDITF,MMEN_DELETEF,MMEN_OSAVE,MMEN_ORESET,MMEN_SELALL,MMEN_SELNONE,MMEN_SELTOGG,MMEN_SEARCH,MMEN_FILTER,MMEN_DELDEL,MMEN_INDEX,MMEN_FLUSH,MMEN_IMPORT,MMEN_EXPORT,MMEN_GETMAIL,MMEN_GET1MAIL,MMEN_SENDMAIL,MMEN_EXMAIL,
  2006.        MMEN_READ,MMEN_EDIT,MMEN_MOVE,MMEN_COPY,MMEN_DELETE,MMEN_PRINT,MMEN_SAVE,MMEN_DETACH,MMEN_CROP,MMEN_EXPMSG,MMEN_NEW,MMEN_REPLY,MMEN_FORWARD,MMEN_BOUNCE,MMEN_SAVEADDR,MMEN_TOUNREAD,MMEN_TOREAD,MMEN_TOHOLD,MMEN_TOQUEUED,MMEN_CHSUBJ,MMEN_SEND,
  2007.        MMEN_ABOOK,MMEN_CONFIG,MMEN_USER,MMEN_MUI,MMEN_SCRIPT };
  2008. #define MMEN_MACRO   100
  2009. #define MMEN_POPHOST 150
  2010.  
  2011. /// MA_SetupDynamicMenus
  2012. //  Updates ARexx and POP3 account menu items
  2013. void MA_SetupDynamicMenus(void)
  2014. {
  2015.    int i;
  2016.    static char *shortcuts[10] = { "0","1","2","3","4","5","6","7","8","9" };
  2017.  
  2018.    /* Scripts menu */
  2019.  
  2020.    if (G->MA->GUI.MN_REXX)
  2021.       DoMethod(G->MA->GUI.MS_MAIN, MUIM_Family_Remove, G->MA->GUI.MN_REXX);
  2022.  
  2023.    G->MA->GUI.MN_REXX = MenuObject,
  2024.       MUIA_Menu_Title, GetStr(MSG_MA_Scripts),
  2025.       MUIA_Family_Child, MenuitemObject,
  2026.          MUIA_Menuitem_Title, GetStr(MSG_MA_ExecuteScript),
  2027.          MUIA_Menuitem_Shortcut, ".", MUIA_UserData, MMEN_SCRIPT,
  2028.          End,
  2029.       MUIA_Family_Child, MenuitemObject,
  2030.          MUIA_Menuitem_Title, NM_BARLABEL,
  2031.          End,
  2032.       End;
  2033.  
  2034.    for (i = 0; i < 10; i++) if (C->RX[i].Script[0])
  2035.       DoMethod(G->MA->GUI.MN_REXX, MUIM_Family_AddTail, MenuitemObject,
  2036.          MUIA_Menuitem_Title, C->RX[i].Name,
  2037.          MUIA_Menuitem_Shortcut, shortcuts[i],
  2038.          MUIA_UserData, MMEN_MACRO+i, End);
  2039.  
  2040.    DoMethod(G->MA->GUI.MS_MAIN, MUIM_Family_AddTail, G->MA->GUI.MN_REXX);
  2041.  
  2042.    /* 'Folder/Check single account' menu */
  2043.  
  2044.    if (G->MA->GUI.MI_CSINGLE)
  2045.       DoMethod(G->MA->GUI.MN_FOLDER, MUIM_Family_Remove, G->MA->GUI.MI_CSINGLE);
  2046.  
  2047.    G->MA->GUI.MI_CSINGLE = MenuitemObject,
  2048.       MUIA_Menuitem_Title, GetStr(MSG_MA_CheckSingle),
  2049.       End;
  2050.  
  2051.    for (i = 0; i < MAXP3; i++) if (C->P3[i])
  2052.    {
  2053.       sprintf(C->P3[i]->Account, "%s@%s", C->P3[i]->User, C->P3[i]->Server);
  2054.  
  2055.       /* Warning: Small memory leak here, each time this function is called,
  2056.                   since the strdup()'ed string doesn't get free()'d anywhere,
  2057.                   before program exit. The Menuitem class does *not* have a
  2058.                   private buffer for the string!
  2059.       */
  2060.  
  2061.       DoMethod(G->MA->GUI.MI_CSINGLE, MUIM_Family_AddTail, MenuitemObject,
  2062.          MUIA_Menuitem_Title, strdup(C->P3[i]->Account),
  2063.          MUIA_UserData, MMEN_POPHOST+i,
  2064.          End);
  2065.    }
  2066.  
  2067.    DoMethod(G->MA->GUI.MN_FOLDER, MUIM_Family_AddTail, G->MA->GUI.MI_CSINGLE);
  2068. }
  2069.  
  2070. ///
  2071. /// MA_MakeMAFormat
  2072. //  Creates format definition for message listview
  2073. void MA_MakeMAFormat(APTR lv)
  2074. {
  2075.    int i;
  2076.    int defwidth[MACOLNUM] = { -1,-1,-1,-1,-1,-1,-1 };
  2077.    char format[SIZE_LARGE];
  2078.    BOOL first = TRUE;
  2079.    *format = 0;
  2080.    for (i = 0; i < MACOLNUM; i++) if (C->MessageCols & (1<<i))
  2081.    {
  2082.       if (first) first = FALSE; else strcat(format, " BAR,");
  2083.       sprintf(&format[strlen(format)], "COL=%ld W=%ld", i, defwidth[i]);
  2084.       if (i == 5) strcat(format, " P=\033r");
  2085.    }
  2086.    strcat(format, " BAR");
  2087.    set(lv, MUIA_NList_Format, format);
  2088. }
  2089.  
  2090. ///
  2091. /// MA_New
  2092. //  Creates main window
  2093. struct MA_ClassData *MA_New(void)
  2094. {
  2095.    struct MA_ClassData *data;
  2096.   
  2097.    if ((data = calloc(1,sizeof(struct MA_ClassData))))
  2098.    {
  2099.       APTR tb_butt[18] = { MSG_MA_TBRead,MSG_MA_TBEdit,MSG_MA_TBMove,MSG_MA_TBDelete,MSG_MA_TBGetAddr,MSG_Space,
  2100.                            MSG_MA_TBWrite,MSG_MA_TBReply,MSG_MA_TBForward,MSG_Space,
  2101.                            MSG_MA_TBGetMail,MSG_MA_TBSendAll,MSG_Space,
  2102.                            MSG_MA_TBFilter,MSG_MA_TBFind,MSG_MA_TBAddrBook,MSG_MA_TBConfig,NULL };
  2103.       APTR tb_help[18] = { MSG_HELP_MA_BT_READ,MSG_HELP_MA_BT_EDIT,MSG_HELP_MA_BT_MOVE,MSG_HELP_MA_BT_DELETE,MSG_HELP_MA_BT_GETADDRESS,NULL,
  2104.                            MSG_HELP_MA_BT_WRITE,MSG_HELP_MA_BT_REPLY,MSG_HELP_MA_BT_FORWARD,NULL,
  2105.                            MSG_HELP_MA_BT_POPNOW,MSG_HELP_MA_BT_SENDALL,NULL,
  2106.                            MSG_HELP_MA_BT_FILTER,MSG_HELP_MA_BT_SEARCH,MSG_HELP_MA_BT_ABOOK,MSG_HELP_MA_BT_CONFIG,NULL };
  2107.       int i;
  2108.       char *key = "-repeat 0", *username = C->RealName;
  2109.       struct User *user;
  2110.       for (i = 0; i < 18; i++) SetupToolbar(&(data->GUI.TB_TOOLBAR[i]), tb_butt[i]?(tb_butt[i]==MSG_Space?"":GetStr(tb_butt[i])):NULL, tb_help[i]?GetStr(tb_help[i]):NULL, 0);
  2111.       if ((user = US_GetCurrentUser())) username = user->Name;
  2112.       sprintf(data->WinTitle, GetStr(MSG_MA_WinTitle), __YAM_VERSION, username);
  2113.       data->GUI.MS_MAIN = MenustripObject,
  2114.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_MA_Project),
  2115.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_PROJECT_ABOUT), MMEN_ABOUT),
  2116.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_AboutMUI), MMEN_ABOUTMUI),
  2117.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_PROJECT_CHECKVERSION), MMEN_VERSION),
  2118.             MUIA_Family_Child, data->GUI.MI_ERRORS = MakeMenuitem(GetStr(MSG_MA_LastErrors), MMEN_ERRORS),
  2119.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2120.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_Restart), MMEN_LOGIN),
  2121.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_Hide), MMEN_HIDE),
  2122.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_Quit), MMEN_QUIT),
  2123.          End,
  2124.          MUIA_Family_Child, data->GUI.MN_FOLDER = MenuObject, MUIA_Menu_Title, GetStr(MSG_Folder),
  2125.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_FOLDER_NEWFOLDER), MMEN_NEWF),
  2126.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_FOLDER_NEWSEPARATOR), MMEN_NEWS),
  2127.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_FOLDER_EDIT), MMEN_EDITF),
  2128.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_FOLDER_DELETE), MMEN_DELETEF),
  2129.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, GetStr(MSG_MA_SortOrder),
  2130.                MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_OSave), MMEN_OSAVE),
  2131.                MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_Reset), MMEN_ORESET),
  2132.             End,
  2133.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2134.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_MSearch), MMEN_SEARCH),
  2135.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_MFilter), MMEN_FILTER),
  2136.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2137.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_RemoveDeleted), MMEN_DELDEL),
  2138.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_UpdateIndex), MMEN_INDEX),
  2139.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_FlushIndices), MMEN_FLUSH),
  2140.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2141.             MUIA_Family_Child, data->GUI.MI_IMPORT = MakeMenuitem(GetStr(MSG_FOLDER_IMPORT), MMEN_IMPORT),
  2142.             MUIA_Family_Child, data->GUI.MI_EXPORT = MakeMenuitem(GetStr(MSG_FOLDER_EXPORT), MMEN_EXPORT),
  2143.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2144.             MUIA_Family_Child, data->GUI.MI_SENDALL = MakeMenuitem(GetStr(MSG_MA_MSendAll), MMEN_SENDMAIL),
  2145.             MUIA_Family_Child, data->GUI.MI_EXCHANGE = MakeMenuitem(GetStr(MSG_MA_Exchange), MMEN_EXMAIL),
  2146.             MUIA_Family_Child, data->GUI.MI_GETMAIL = MakeMenuitem(GetStr(MSG_MA_MGetMail), MMEN_GETMAIL),
  2147.         End,
  2148.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_Message),
  2149.             MUIA_Family_Child, data->GUI.MI_READ = MakeMenuitem(GetStr(MSG_MA_MRead), MMEN_READ),
  2150.             MUIA_Family_Child, data->GUI.MI_EDIT = MakeMenuitem(GetStr(MSG_MESSAGE_EDIT), MMEN_EDIT),
  2151.             MUIA_Family_Child, data->GUI.MI_MOVE = MakeMenuitem(GetStr(MSG_MESSAGE_MOVE), MMEN_MOVE),
  2152.             MUIA_Family_Child, data->GUI.MI_COPY = MakeMenuitem(GetStr(MSG_MESSAGE_COPY), MMEN_COPY),
  2153.             MUIA_Family_Child, data->GUI.MI_DELETE = MenuitemObject, MUIA_Menuitem_Title, GetStr(MSG_MA_MDelete), MUIA_Menuitem_Shortcut, "Del", MUIA_Menuitem_CommandString,TRUE, MUIA_UserData, MMEN_DELETE, End,
  2154.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2155.             MUIA_Family_Child, data->GUI.MI_PRINT = MakeMenuitem(GetStr(MSG_MESSAGE_PRINT), MMEN_PRINT),
  2156.             MUIA_Family_Child, data->GUI.MI_SAVE = MakeMenuitem(GetStr(MSG_MESSAGE_SAVE), MMEN_SAVE),
  2157.             MUIA_Family_Child, data->GUI.MI_ATTACH = MenuitemObject, MUIA_Menuitem_Title, GetStr(MSG_Attachments),
  2158.                MUIA_Family_Child, data->GUI.MI_SAVEATT = MakeMenuitem(GetStr(MSG_MESSAGE_SAVEATT), MMEN_DETACH),
  2159.                MUIA_Family_Child, data->GUI.MI_REMATT = MakeMenuitem(GetStr(MSG_MESSAGE_CROP), MMEN_CROP),
  2160.             End,
  2161.             MUIA_Family_Child, data->GUI.MI_EXPMSG = MakeMenuitem(GetStr(MSG_MESSAGE_EXPORT), MMEN_EXPMSG),
  2162.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2163.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MESSAGE_NEW), MMEN_NEW),
  2164.             MUIA_Family_Child, data->GUI.MI_REPLY = MakeMenuitem(GetStr(MSG_MESSAGE_REPLY), MMEN_REPLY),
  2165.             MUIA_Family_Child, data->GUI.MI_FORWARD = MakeMenuitem(GetStr(MSG_MESSAGE_FORWARD), MMEN_FORWARD),
  2166.             MUIA_Family_Child, data->GUI.MI_BOUNCE = MakeMenuitem(GetStr(MSG_MESSAGE_BOUNCE), MMEN_BOUNCE),
  2167.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2168.             MUIA_Family_Child, data->GUI.MI_GETADDRESS = MakeMenuitem(GetStr(MSG_MESSAGE_GETADDRESS), MMEN_SAVEADDR),
  2169.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, GetStr(MSG_MA_Select),
  2170.                MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_SelectAll), MMEN_SELALL),
  2171.                MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_SelectNone), MMEN_SELNONE),
  2172.                MUIA_Family_Child, MakeMenuitem(GetStr(MSG_MA_SelectToggle), MMEN_SELTOGG),
  2173.             End,
  2174.             MUIA_Family_Child, data->GUI.MI_STATUS = MenuitemObject, MUIA_Menuitem_Title, GetStr(MSG_MA_SetStatus),
  2175.                MUIA_Family_Child, data->GUI.MI_TOUNREAD = MakeMenuitem(GetStr(MSG_MA_ToUnread), MMEN_TOUNREAD),
  2176.                MUIA_Family_Child, data->GUI.MI_TOREAD = MakeMenuitem(GetStr(MSG_MA_ToRead), MMEN_TOREAD),
  2177.                MUIA_Family_Child, data->GUI.MI_TOHOLD = MakeMenuitem(GetStr(MSG_MA_ToHold), MMEN_TOHOLD),
  2178.                MUIA_Family_Child, data->GUI.MI_TOQUEUED = MakeMenuitem(GetStr(MSG_MA_ToQueued), MMEN_TOQUEUED),
  2179.             End,
  2180.             MUIA_Family_Child, data->GUI.MI_CHSUBJ = MakeMenuitem(GetStr(MSG_MA_ChangeSubj), MMEN_CHSUBJ),
  2181.             MUIA_Family_Child, MenuitemObject, MUIA_Menuitem_Title, NM_BARLABEL, End,
  2182.             MUIA_Family_Child, data->GUI.MI_SEND = MakeMenuitem(GetStr(MSG_MA_MSend), MMEN_SEND),
  2183.          End,
  2184.          MUIA_Family_Child, MenuObject, MUIA_Menu_Title, GetStr(MSG_MA_Settings),
  2185.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_SETTINGS_ADDRESSBOOK), MMEN_ABOOK),
  2186.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_SETTINGS_CONFIG), MMEN_CONFIG),
  2187.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_SETTINGS_USERS), MMEN_USER),
  2188.             MUIA_Family_Child, MakeMenuitem(GetStr(MSG_SETTINGS_MUI), MMEN_MUI),
  2189.          End,
  2190.       End,
  2191.       data->GUI.WI = NewObject(CL_MainWin->mcc_Class,NULL,
  2192.          MUIA_Window_Title, data->WinTitle,
  2193.          MUIA_HelpNode, "MA_W",
  2194.          MUIA_Window_ID, MAKE_ID('M','A','I','N'),
  2195.          MUIA_Window_Menustrip, data->GUI.MS_MAIN,
  2196.          WindowContents, VGroup,
  2197.             Child, (C->HideGUIElements & HIDE_TBAR) ?
  2198.                VSpace(1) :
  2199.                (HGroupV,
  2200.                   MUIA_HelpNode, "MA02",
  2201.                   Child, data->GUI.TO_TOOLBAR = ToolbarObject,
  2202.                      MUIA_Toolbar_ImageType,      MUIV_Toolbar_ImageType_File,
  2203.                      MUIA_Toolbar_ImageNormal,    "PROGDIR:Icons/Main.toolbar",
  2204.                      MUIA_Toolbar_ImageGhost,     "PROGDIR:Icons/Main_G.toolbar",
  2205.                      MUIA_Toolbar_ImageSelect,    "PROGDIR:Icons/Main_S.toolbar",
  2206.                      MUIA_Toolbar_Description,    data->GUI.TB_TOOLBAR,
  2207.                      MUIA_Toolbar_ParseUnderscore,TRUE,
  2208.                      MUIA_Font,                   MUIV_Font_Tiny,
  2209.                      MUIA_ShortHelp, TRUE,
  2210.                   End,
  2211.                   Child, HSpace(0),
  2212.                End),
  2213.             Child, HGroup,
  2214.                MUIA_ShowMe, FALSE,
  2215.                Child, data->GUI.BC_STAT[ 0] = MakeStatusFlag("status_unread"),
  2216.                Child, data->GUI.BC_STAT[ 1] = MakeStatusFlag("status_old"),
  2217.                Child, data->GUI.BC_STAT[ 2] = MakeStatusFlag("status_forward"),
  2218.                Child, data->GUI.BC_STAT[ 3] = MakeStatusFlag("status_reply"),
  2219.                Child, data->GUI.BC_STAT[ 4] = MakeStatusFlag("status_waitsend"),
  2220.                Child, data->GUI.BC_STAT[ 5] = MakeStatusFlag("status_error"),
  2221.                Child, data->GUI.BC_STAT[ 6] = MakeStatusFlag("status_hold"),
  2222.                Child, data->GUI.BC_STAT[ 7] = MakeStatusFlag("status_sent"),
  2223.                Child, data->GUI.BC_STAT[ 8] = MakeStatusFlag("status_new"),
  2224.                Child, data->GUI.BC_STAT[ 9] = MakeStatusFlag("status_delete"),
  2225.                Child, data->GUI.BC_STAT[10] = MakeStatusFlag("status_download"),
  2226.                Child, data->GUI.BC_STAT[11] = MakeStatusFlag("status_group"),
  2227.                Child, data->GUI.BC_STAT[12] = MakeStatusFlag("status_urgent"),
  2228.                Child, data->GUI.BC_STAT[13] = MakeStatusFlag("status_attach"),
  2229.                Child, data->GUI.BC_STAT[14] = MakeStatusFlag("status_report"),
  2230.                Child, data->GUI.BC_STAT[15] = MakeStatusFlag("status_crypt"),
  2231.                Child, data->GUI.BC_STAT[16] = MakeStatusFlag("status_signed"),
  2232.                Child, data->GUI.ST_LAYOUT = StringObject,
  2233.                   MUIA_ObjectID, MAKE_ID('S','T','L','A'),
  2234.                   MUIA_String_MaxLen, SIZE_DEFAULT,
  2235.                End,
  2236.             End,
  2237.             Child, HGroup,
  2238.                MUIA_Group_Spacing, 1,
  2239.                Child, data->GUI.LV_FOLDERS = NListviewObject,
  2240.                   MUIA_HelpNode, "MA00",
  2241.                   MUIA_CycleChain, 1,
  2242.                   MUIA_HorizWeight, 30,
  2243.                   MUIA_NListview_NList, data->GUI.NL_FOLDERS = NewObject(CL_FolderList->mcc_Class,NULL,
  2244.                      InputListFrame,
  2245.                      MUIA_NList_MinColSortable      , 0,
  2246.                      MUIA_NList_TitleClick          , TRUE,
  2247.                      MUIA_NList_DragType            , MUIV_NList_DragType_Immediate,
  2248.                      MUIA_NList_DragSortable        , TRUE,
  2249.                      MUIA_NList_CompareHook2        , &MA_LV_FCmp2Hook,
  2250.                      MUIA_NList_DisplayHook         , &MA_LV_FDspFuncHook,
  2251.                      MUIA_NList_ConstructHook       , &MA_LV_FConHook,
  2252.                      MUIA_NList_DestructHook        , &GeneralDesHook,
  2253.                      MUIA_NList_TitleSeparator      , TRUE,
  2254.                      MUIA_NList_AutoVisible         , TRUE,
  2255.                      MUIA_NList_Title               , TRUE,
  2256.                      MUIA_NList_DoubleClick         , TRUE,
  2257.                      MUIA_NList_DefaultObjectOnClick, FALSE,
  2258.                      MUIA_Font                      , C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
  2259.                      MUIA_Dropable                  , TRUE,
  2260. //                     MUIA_ContextMenu               , NULL,
  2261.                      MUIA_NList_Exports             , MUIV_NList_Exports_ColWidth|MUIV_NList_Exports_ColOrder,
  2262.                      MUIA_NList_Imports             , MUIV_NList_Imports_ColWidth|MUIV_NList_Imports_ColOrder,
  2263.                      MUIA_ObjectID, MAKE_ID('N','L','0','1'),
  2264.                   End,
  2265.                End,
  2266.                Child, BalanceObject, End,
  2267.                Child, data->GUI.LV_MAILS = NListviewObject,
  2268.                   MUIA_HelpNode, "MA01",
  2269.                   MUIA_CycleChain,1,
  2270.                   MUIA_NListview_NList, data->GUI.NL_MAILS = NListObject,
  2271.                      MUIA_NList_MinColSortable, 0,
  2272.                      MUIA_NList_TitleClick    , TRUE,
  2273.                      MUIA_NList_TitleClick2   , TRUE,
  2274.                      MUIA_NList_DragType      , MUIV_NList_DragType_Default,
  2275.                      MUIA_NList_MultiSelect   , MUIV_NList_MultiSelect_Default,
  2276.                      MUIA_NList_CompareHook2  , &MA_LV_Cmp2Hook,
  2277.                      MUIA_NList_DisplayHook   , &MA_LV_DspFuncHook,
  2278.                      MUIA_NList_AutoVisible   , TRUE,
  2279.                      MUIA_NList_Title         , TRUE,
  2280.                      MUIA_NList_TitleSeparator, TRUE,
  2281.                      MUIA_NList_DefaultObjectOnClick, TRUE,
  2282.                      MUIA_Font, C->FixedFontList ? MUIV_NList_Font_Fixed : MUIV_NList_Font,
  2283. //                     MUIA_ContextMenu         , NULL,
  2284.                      MUIA_NList_Exports       , MUIV_NList_Exports_ColWidth|MUIV_NList_Exports_ColOrder,
  2285.                      MUIA_NList_Imports       , MUIV_NList_Imports_ColWidth|MUIV_NList_Imports_ColOrder,
  2286.                      MUIA_ObjectID, MAKE_ID('N','L','0','2'),
  2287.                   End,
  2288.                End,
  2289.             End,
  2290.             Child, data->GUI.GA_INFO = GaugeObject,
  2291.                GaugeFrame,
  2292.                MUIA_Gauge_Horiz   , TRUE,
  2293.                MUIA_Gauge_InfoText, " ",
  2294.                MUIA_ShowMe        , !(C->HideGUIElements & HIDE_INFO) ,
  2295.             End,
  2296.          End,
  2297.       End;
  2298.       if (data->GUI.WI)
  2299.       {
  2300.          MA_MakeFOFormat(data->GUI.NL_FOLDERS);
  2301.          MA_MakeMAFormat(data->GUI.NL_MAILS);
  2302.          DoMethod(G->App, OM_ADDMEMBER, data->GUI.WI);
  2303.          for (i = 0; i < 17; i++) DoMethod(data->GUI.NL_MAILS, MUIM_NList_UseImage, data->GUI.BC_STAT[i], i, 0);
  2304.          DoMethod(data->GUI.NL_FOLDERS, MUIM_NList_UseImage, data->GUI.BC_STAT[15], 0, 0);
  2305.          set(data->GUI.WI,MUIA_Window_DefaultObject,data->GUI.LV_MAILS);
  2306.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOUT     ,G->AY_Win,3,MUIM_Set                ,MUIA_Window_Open,TRUE);
  2307.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_VERSION   ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_CheckVersionHook);
  2308.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ERRORS    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ShowErrorsHook);
  2309.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_LOGIN     ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,ID_RESTART);
  2310.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_HIDE      ,MUIV_Notify_Application  ,3,MUIM_Set                 ,MUIA_Application_Iconified,TRUE);
  2311.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_QUIT      ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  2312.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEWF      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_NewFolderHook);
  2313.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEWS      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_NewSeparatorHook);
  2314.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EDITF     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_EditFolderHook);
  2315.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELETEF   ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_DeleteFolderHook);
  2316.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_OSAVE     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&FO_SetOrderHook,SO_SAVE);
  2317.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ORESET    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&FO_SetOrderHook,SO_RESET);
  2318.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELALL    ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_On,NULL);
  2319.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELNONE   ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Off,NULL);
  2320.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SELTOGG   ,data->GUI.NL_MAILS,4,MUIM_NList_Select,MUIV_NList_Select_All,MUIV_NList_Select_Toggle,NULL);
  2321.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SEARCH    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FI_OpenHook);
  2322.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FILTER    ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_ApplyRulesHook,APPLY_USER,0,FALSE);
  2323.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELDEL    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_DeleteDeletedHook);
  2324.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_INDEX     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_RescanIndexHook);
  2325.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FLUSH     ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_FlushIndexHook);
  2326.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOOK     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&AB_OpenHook,ABM_EDIT);
  2327.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXPORT    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ExportMessagesHook,TRUE);
  2328.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_IMPORT    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ImportMessagesHook);
  2329.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_GETMAIL   ,MUIV_Notify_Application  ,6,MUIM_CallHook            ,&MA_PopNowHook,POP_USER,-1,0,FALSE);
  2330.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SENDMAIL  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SendHook,SEND_ALL);
  2331.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXMAIL    ,MUIV_Notify_Application  ,6,MUIM_CallHook            ,&MA_PopNowHook,POP_USER,-1,IEQUALIFIER_LSHIFT,FALSE);
  2332.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_READ      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ReadMessageHook);
  2333.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EDIT      ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_EDIT,0,FALSE);
  2334.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_MOVE      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_MoveMessageHook);
  2335.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_COPY      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_CopyMessageHook);
  2336.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DELETE    ,MUIV_Notify_Application  ,4,MUIM_CallHook            ,&MA_DeleteMessageHook,0,FALSE);
  2337.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_PRINT     ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SavePrintHook,TRUE);
  2338.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SAVE      ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SavePrintHook,FALSE);
  2339.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_DETACH    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SaveAttachHook);
  2340.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CROP      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_RemoveAttachHook);
  2341.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_EXPMSG    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ExportMessagesHook,FALSE);
  2342.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_NEW       ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_NEW,0,FALSE);
  2343.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_REPLY     ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_REPLY,0,FALSE);
  2344.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_FORWARD   ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_FORWARD,0,FALSE);
  2345.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_BOUNCE    ,MUIV_Notify_Application  ,5,MUIM_CallHook            ,&MA_NewMessageHook,NEW_BOUNCE,0,FALSE);
  2346.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SAVEADDR  ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_GetAddressHook);
  2347.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CHSUBJ    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSubjectHook);
  2348.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SEND      ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SendHook,SEND_ACTIVE);
  2349.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOREAD    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_OLD);
  2350.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOUNREAD  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_UNR);
  2351.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOHOLD    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_HLD);
  2352.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_TOQUEUED  ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_SetStatusToHook,STATUS_WFS);
  2353.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_CONFIG    ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&CO_OpenHook);
  2354.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_USER      ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&US_OpenHook);
  2355.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_MUI       ,MUIV_Notify_Application  ,2,MUIM_Application_OpenConfigWindow,0);
  2356.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_ABOUTMUI  ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_AboutMUIHook);
  2357.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_MenuAction   ,MMEN_SCRIPT    ,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_CallRexxHook,-1);
  2358.          for (i = 0; i < 10; i++) DoMethod(data->GUI.WI,MUIM_Notify,MUIA_Window_MenuAction,MMEN_MACRO+i,MUIV_Notify_Application,3,MUIM_CallHook        ,&MA_CallRexxHook, i);
  2359.          for (i = 0; i < MAXP3; i++) DoMethod(data->GUI.WI,MUIM_Notify,MUIA_Window_MenuAction,MMEN_POPHOST+i,MUIV_Notify_Application,6,MUIM_CallHook   ,&MA_PopNowHook,POP_USER,i,0,FALSE);
  2360.          if (data->GUI.TO_TOOLBAR)
  2361.          {
  2362.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 0, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_ReadMessageHook);
  2363.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 1, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_EDIT,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2364.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 2, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_MoveMessageHook);
  2365.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 3, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,4,MUIM_CallHook,&MA_DeleteMessageHook,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2366.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 4, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&MA_GetAddressHook);
  2367.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 6, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_NEW,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2368.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 7, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_REPLY,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2369.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify, 8, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_NewMessageHook,NEW_FORWARD,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2370.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,10, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,9,MUIM_Application_PushMethod,G->App,6,MUIM_CallHook,&MA_PopNowHook,POP_USER,-1,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2371.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,11, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,7,MUIM_Application_PushMethod,G->App,3,MUIM_CallHook,&MA_SendHook,SEND_ALL);
  2372.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,13, MUIV_Toolbar_Notify_Pressed,MUIV_EveryTime,MUIV_Notify_Application,5,MUIM_CallHook,&MA_ApplyRulesHook,APPLY_USER,MUIV_Toolbar_Qualifier,MUIV_TriggerValue);
  2373.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,14, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&FI_OpenHook);
  2374.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,15, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,3,MUIM_CallHook,&AB_OpenHook,ABM_EDIT);
  2375.             DoMethod(data->GUI.TO_TOOLBAR     ,MUIM_Toolbar_Notify,16, MUIV_Toolbar_Notify_Pressed,FALSE,MUIV_Notify_Application,2,MUIM_CallHook,&CO_OpenHook);
  2376.          }
  2377.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_DoubleClick   ,MUIV_EveryTime,MUIV_Notify_Application  ,3,MUIM_CallHook            ,&MA_ReadMessageHook,FALSE);
  2378.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_TitleClick    ,MUIV_EveryTime,MUIV_Notify_Self         ,4,MUIM_NList_Sort3         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values,MUIV_NList_Sort3_SortType_Both);
  2379.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_TitleClick2   ,MUIV_EveryTime,MUIV_Notify_Self         ,4,MUIM_NList_Sort3         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values,MUIV_NList_Sort3_SortType_2);
  2380.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SortType      ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark,MUIV_TriggerValue);
  2381.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SortType2     ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark2,MUIV_TriggerValue);
  2382.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_SelectChange  ,TRUE          ,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSelectedHook);
  2383.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeSelectedHook);
  2384.          DoMethod(data->GUI.NL_MAILS       ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SetMessageInfoHook);
  2385.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_DoubleClick   ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&FO_EditFolderHook);
  2386.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_TitleClick    ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_NList_Sort2         ,MUIV_TriggerValue,MUIV_NList_SortTypeAdd_2Values);
  2387.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_SortType      ,MUIV_EveryTime,MUIV_Notify_Self         ,3,MUIM_Set                 ,MUIA_NList_TitleMark,MUIV_TriggerValue);
  2388.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_ChangeFolderHook);
  2389.          DoMethod(data->GUI.NL_FOLDERS     ,MUIM_Notify,MUIA_NList_Active        ,MUIV_EveryTime,MUIV_Notify_Application  ,2,MUIM_CallHook            ,&MA_SetFolderInfoHook);
  2390.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_CloseRequest ,TRUE          ,MUIV_Notify_Application  ,2,MUIM_Application_ReturnID,ID_CLOSEALL);
  2391.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_InputEvent   ,"-repeat del" ,MUIV_Notify_Application  ,4,MUIM_CallHook            ,&MA_DelKeyHook,FALSE);
  2392.          DoMethod(data->GUI.WI             ,MUIM_Notify,MUIA_Window_InputEvent   ,"-repeat shift del" ,MUIV_Notify_Application  ,4,MUIM_CallHook      ,&MA_DelKeyHook,TRUE);
  2393.          DoMethod(G->App                   ,MUIM_Notify,MUIA_Application_Iconified,FALSE        ,data->GUI.WI             ,3,MUIM_Set                 ,MUIA_Window_Open,TRUE);
  2394.          for (i = 0; i < 10; i++)
  2395.          {
  2396.             key[8] = '0'+i;
  2397.             DoMethod(data->GUI.WI, MUIM_Notify,MUIA_Window_InputEvent, key, data->GUI.NL_FOLDERS, 3, MUIM_Set, MUIA_NList_Active, i);
  2398.          }
  2399.          return data;
  2400.       }
  2401.       free(data);
  2402.    }
  2403.    return NULL;
  2404. }
  2405. ///
  2406.  
  2407.